blob: f96aef8577578749fca2e8841334e8b07b453545 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
Dianne Hackbornb8d81672009-11-20 14:26:42 -080020#define DEBUG_STYLES(x) //x
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080021#define THROW_ON_BAD_ID 0
Dianne Hackbornb8d81672009-11-20 14:26:42 -080022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023#include <android_runtime/android_util_AssetManager.h>
24
25#include "jni.h"
26#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070027#include "ScopedStringChars.h"
28#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include "android_util_Binder.h"
30#include <utils/misc.h>
31#include <android_runtime/AndroidRuntime.h>
32#include <utils/Log.h>
33
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080034#include <androidfw/Asset.h>
35#include <androidfw/AssetManager.h>
36#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
38#include <stdio.h>
39
40namespace android {
41
42// ----------------------------------------------------------------------------
43
44static struct typedvalue_offsets_t
45{
46 jfieldID mType;
47 jfieldID mData;
48 jfieldID mString;
49 jfieldID mAssetCookie;
50 jfieldID mResourceId;
51 jfieldID mChangingConfigurations;
52 jfieldID mDensity;
53} gTypedValueOffsets;
54
55static struct assetfiledescriptor_offsets_t
56{
57 jfieldID mFd;
58 jfieldID mStartOffset;
59 jfieldID mLength;
60} gAssetFileDescriptorOffsets;
61
62static struct assetmanager_offsets_t
63{
64 jfieldID mObject;
65} gAssetManagerOffsets;
66
67jclass g_stringClass = NULL;
68
69// ----------------------------------------------------------------------------
70
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070072 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 STYLE_TYPE = 0,
74 STYLE_DATA = 1,
75 STYLE_ASSET_COOKIE = 2,
76 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070077 STYLE_CHANGING_CONFIGURATIONS = 4,
78 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079};
80
81static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
82 const Res_value& value, uint32_t ref, ssize_t block,
83 uint32_t typeSpecFlags, ResTable_config* config = NULL);
84
85jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
86 const Res_value& value, uint32_t ref, ssize_t block,
87 uint32_t typeSpecFlags, ResTable_config* config)
88{
89 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
90 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +000091 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
93 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
94 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
95 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
96 typeSpecFlags);
97 if (config != NULL) {
98 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
99 }
100 return block;
101}
102
103// ----------------------------------------------------------------------------
104
105// this guy is exported to other jni routines
106AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
107{
Ashok Bhat896043d2014-01-17 16:02:38 +0000108 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
109 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 if (am != NULL) {
111 return am;
112 }
113 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
114 return NULL;
115}
116
Ashok Bhat896043d2014-01-17 16:02:38 +0000117static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 jstring fileName, jint mode)
119{
120 AssetManager* am = assetManagerForJavaObject(env, clazz);
121 if (am == NULL) {
122 return 0;
123 }
124
Steve Block71f2cf12011-10-20 11:56:00 +0100125 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126
Elliott Hughes69a017b2011-04-08 14:10:28 -0700127 ScopedUtfChars fileName8(env, fileName);
128 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000129 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 return -1;
131 }
132
133 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
134 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700135 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 return -1;
137 }
138
Elliott Hughes69a017b2011-04-08 14:10:28 -0700139 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700142 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 return -1;
144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
146 //printf("Created Asset Stream: %p\n", a);
147
Ashok Bhat896043d2014-01-17 16:02:38 +0000148 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149}
150
151static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
152{
Kenny Rootddb76c42010-11-24 12:56:06 -0800153 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 int fd = a->openFileDescriptor(&startOffset, &length);
155 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700158 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 "This file can not be opened as a file descriptor; it is probably compressed");
160 return NULL;
161 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
164 if (offsets == NULL) {
165 close(fd);
166 return NULL;
167 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 offsets[0] = startOffset;
170 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700173
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700174 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 if (fileDesc == NULL) {
176 close(fd);
177 return NULL;
178 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 return newParcelFileDescriptor(env, fileDesc);
181}
182
183static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
184 jstring fileName, jlongArray outOffsets)
185{
186 AssetManager* am = assetManagerForJavaObject(env, clazz);
187 if (am == NULL) {
188 return NULL;
189 }
190
Steve Block71f2cf12011-10-20 11:56:00 +0100191 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
Elliott Hughes69a017b2011-04-08 14:10:28 -0700193 ScopedUtfChars fileName8(env, fileName);
194 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 return NULL;
196 }
197
Elliott Hughes69a017b2011-04-08 14:10:28 -0700198 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
200 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700201 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 return NULL;
203 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204
205 //printf("Created Asset Stream: %p\n", a);
206
207 return returnParcelFileDescriptor(env, a, outOffsets);
208}
209
Ashok Bhat896043d2014-01-17 16:02:38 +0000210static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 jint cookie,
212 jstring fileName,
213 jint mode)
214{
215 AssetManager* am = assetManagerForJavaObject(env, clazz);
216 if (am == NULL) {
217 return 0;
218 }
219
Steve Block71f2cf12011-10-20 11:56:00 +0100220 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
Elliott Hughes69a017b2011-04-08 14:10:28 -0700222 ScopedUtfChars fileName8(env, fileName);
223 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 return -1;
225 }
226
227 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
228 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700229 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 return -1;
231 }
232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000234 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
235 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700236 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237
238 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700239 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 return -1;
241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
243 //printf("Created Asset Stream: %p\n", a);
244
Ashok Bhat896043d2014-01-17 16:02:38 +0000245 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246}
247
248static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
249 jint cookie,
250 jstring fileName,
251 jlongArray outOffsets)
252{
253 AssetManager* am = assetManagerForJavaObject(env, clazz);
254 if (am == NULL) {
255 return NULL;
256 }
257
Steve Block71f2cf12011-10-20 11:56:00 +0100258 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259
Elliott Hughes69a017b2011-04-08 14:10:28 -0700260 ScopedUtfChars fileName8(env, fileName);
261 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 return NULL;
263 }
264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000266 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700267 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
269 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700270 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 return NULL;
272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 //printf("Created Asset Stream: %p\n", a);
275
276 return returnParcelFileDescriptor(env, a, outOffsets);
277}
278
279static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
280 jstring fileName)
281{
282 AssetManager* am = assetManagerForJavaObject(env, clazz);
283 if (am == NULL) {
284 return NULL;
285 }
286
Elliott Hughes69a017b2011-04-08 14:10:28 -0700287 ScopedUtfChars fileName8(env, fileName);
288 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 return NULL;
290 }
291
Elliott Hughes69a017b2011-04-08 14:10:28 -0700292 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
294 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700295 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 return NULL;
297 }
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 size_t N = dir->getFileCount();
300
301 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100302 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 delete dir;
305 return NULL;
306 }
307
308 for (size_t i=0; i<N; i++) {
309 const String8& name = dir->getFileName(i);
310 jstring str = env->NewStringUTF(name.string());
311 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 delete dir;
313 return NULL;
314 }
315 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700316 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 }
318
319 delete dir;
320
321 return array;
322}
323
324static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000325 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326{
Ashok Bhat896043d2014-01-17 16:02:38 +0000327 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328
329 //printf("Destroying Asset Stream: %p\n", a);
330
331 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700332 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 return;
334 }
335
336 delete a;
337}
338
339static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000340 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341{
Ashok Bhat896043d2014-01-17 16:02:38 +0000342 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
344 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700345 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return -1;
347 }
348
349 uint8_t b;
350 ssize_t res = a->read(&b, 1);
351 return res == 1 ? b : -1;
352}
353
354static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000355 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 jint off, jint len)
357{
Ashok Bhat896043d2014-01-17 16:02:38 +0000358 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
360 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700361 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 return -1;
363 }
364
365 if (len == 0) {
366 return 0;
367 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 jsize bLen = env->GetArrayLength(bArray);
370 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700371 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 return -1;
373 }
374
375 jbyte* b = env->GetByteArrayElements(bArray, NULL);
376 ssize_t res = a->read(b+off, len);
377 env->ReleaseByteArrayElements(bArray, b, 0);
378
Ashok Bhat896043d2014-01-17 16:02:38 +0000379 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380
381 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700382 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384 return -1;
385}
386
387static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000388 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 jlong offset, jint whence)
390{
Ashok Bhat896043d2014-01-17 16:02:38 +0000391 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392
393 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700394 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 return -1;
396 }
397
398 return a->seek(
399 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
400}
401
402static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000403 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404{
Ashok Bhat896043d2014-01-17 16:02:38 +0000405 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406
407 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700408 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 return -1;
410 }
411
412 return a->getLength();
413}
414
415static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000416 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417{
Ashok Bhat896043d2014-01-17 16:02:38 +0000418 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419
420 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700421 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 return -1;
423 }
424
425 return a->getRemainingLength();
426}
427
428static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
429 jstring path)
430{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700431 ScopedUtfChars path8(env, path);
432 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800433 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
435
436 AssetManager* am = assetManagerForJavaObject(env, clazz);
437 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800438 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 }
440
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000441 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700442 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000444 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445}
446
447static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
448{
449 AssetManager* am = assetManagerForJavaObject(env, clazz);
450 if (am == NULL) {
451 return JNI_TRUE;
452 }
453 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
454}
455
456static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
457 jstring locale)
458{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700459 ScopedUtfChars locale8(env, locale);
460 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 return;
462 }
463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 AssetManager* am = assetManagerForJavaObject(env, clazz);
465 if (am == NULL) {
466 return;
467 }
468
Elliott Hughes69a017b2011-04-08 14:10:28 -0700469 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470}
471
472static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
473{
474 Vector<String8> locales;
475
476 AssetManager* am = assetManagerForJavaObject(env, clazz);
477 if (am == NULL) {
478 return NULL;
479 }
480
481 am->getLocales(&locales);
482
483 const int N = locales.size();
484
485 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
486 if (result == NULL) {
487 return NULL;
488 }
489
490 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700491 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700492 if (str == NULL) {
493 return NULL;
494 }
495 env->SetObjectArrayElement(result, i, str);
496 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 }
498
499 return result;
500}
501
502static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
503 jint mcc, jint mnc,
504 jstring locale, jint orientation,
505 jint touchscreen, jint density,
506 jint keyboard, jint keyboardHidden,
507 jint navigation,
508 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700509 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700510 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100511 jint screenLayout, jint uiMode,
512 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513{
514 AssetManager* am = assetManagerForJavaObject(env, clazz);
515 if (am == NULL) {
516 return;
517 }
518
519 ResTable_config config;
520 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 config.mcc = (uint16_t)mcc;
525 config.mnc = (uint16_t)mnc;
526 config.orientation = (uint8_t)orientation;
527 config.touchscreen = (uint8_t)touchscreen;
528 config.density = (uint16_t)density;
529 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700530 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 config.navigation = (uint8_t)navigation;
532 config.screenWidth = (uint16_t)screenWidth;
533 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700534 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700535 config.screenWidthDp = (uint16_t)screenWidthDp;
536 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700537 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100538 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 config.sdkVersion = (uint16_t)sdkVersion;
540 config.minorVersion = 0;
541 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
544}
545
546static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
547 jstring name,
548 jstring defType,
549 jstring defPackage)
550{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700551 ScopedStringChars name16(env, name);
552 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 return 0;
554 }
555
556 AssetManager* am = assetManagerForJavaObject(env, clazz);
557 if (am == NULL) {
558 return 0;
559 }
560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 const char16_t* defType16 = defType
562 ? env->GetStringChars(defType, NULL) : NULL;
563 jsize defTypeLen = defType
564 ? env->GetStringLength(defType) : 0;
565 const char16_t* defPackage16 = defPackage
566 ? env->GetStringChars(defPackage, NULL) : NULL;
567 jsize defPackageLen = defPackage
568 ? env->GetStringLength(defPackage) : 0;
569
570 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700571 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572
573 if (defPackage16) {
574 env->ReleaseStringChars(defPackage, defPackage16);
575 }
576 if (defType16) {
577 env->ReleaseStringChars(defType, defType16);
578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800579
580 return ident;
581}
582
583static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
584 jint resid)
585{
586 AssetManager* am = assetManagerForJavaObject(env, clazz);
587 if (am == NULL) {
588 return NULL;
589 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700592 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 return NULL;
594 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 String16 str;
597 if (name.package != NULL) {
598 str.setTo(name.package, name.packageLen);
599 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700600 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 if (str.size() > 0) {
602 char16_t div = ':';
603 str.append(&div, 1);
604 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700605 if (name.type8 != NULL) {
606 str.append(String16(name.type8, name.typeLen));
607 } else {
608 str.append(name.type, name.typeLen);
609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700611 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 if (str.size() > 0) {
613 char16_t div = '/';
614 str.append(&div, 1);
615 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700616 if (name.name8 != NULL) {
617 str.append(String16(name.name8, name.nameLen));
618 } else {
619 str.append(name.name, name.nameLen);
620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 return env->NewString((const jchar*)str.string(), str.size());
624}
625
626static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
627 jint resid)
628{
629 AssetManager* am = assetManagerForJavaObject(env, clazz);
630 if (am == NULL) {
631 return NULL;
632 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700635 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 return NULL;
637 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800639 if (name.package != NULL) {
640 return env->NewString((const jchar*)name.package, name.packageLen);
641 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 return NULL;
644}
645
646static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
647 jint resid)
648{
649 AssetManager* am = assetManagerForJavaObject(env, clazz);
650 if (am == NULL) {
651 return NULL;
652 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700655 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 return NULL;
657 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700658
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700659 if (name.type8 != NULL) {
660 return env->NewStringUTF(name.type8);
661 }
662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 if (name.type != NULL) {
664 return env->NewString((const jchar*)name.type, name.typeLen);
665 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 return NULL;
668}
669
670static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
671 jint resid)
672{
673 AssetManager* am = assetManagerForJavaObject(env, clazz);
674 if (am == NULL) {
675 return NULL;
676 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700679 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 return NULL;
681 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700682
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700683 if (name.name8 != NULL) {
684 return env->NewStringUTF(name.name8);
685 }
686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 if (name.name != NULL) {
688 return env->NewString((const jchar*)name.name, name.nameLen);
689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 return NULL;
692}
693
694static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
695 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700696 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 jobject outValue,
698 jboolean resolve)
699{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800700 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800701 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700702 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 AssetManager* am = assetManagerForJavaObject(env, clazz);
705 if (am == NULL) {
706 return 0;
707 }
708 const ResTable& res(am->getResources());
709
710 Res_value value;
711 ResTable_config config;
712 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700713 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800714#if THROW_ON_BAD_ID
715 if (block == BAD_INDEX) {
716 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
717 return 0;
718 }
719#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 uint32_t ref = ident;
721 if (resolve) {
Dianne Hackbornfb5c3db2012-05-18 15:24:24 -0700722 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800723#if THROW_ON_BAD_ID
724 if (block == BAD_INDEX) {
725 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
726 return 0;
727 }
728#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000730 if (block >= 0) {
731 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
732 }
733
734 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735}
736
737static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
738 jint ident, jint bagEntryId,
739 jobject outValue, jboolean resolve)
740{
741 AssetManager* am = assetManagerForJavaObject(env, clazz);
742 if (am == NULL) {
743 return 0;
744 }
745 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 // Now lock down the resource object and start pulling stuff from it.
748 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 ssize_t block = -1;
751 Res_value value;
752
753 const ResTable::bag_entry* entry = NULL;
754 uint32_t typeSpecFlags;
755 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
756
757 for (ssize_t i=0; i<entryCount; i++) {
758 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
759 block = entry->stringBlock;
760 value = entry->map.value;
761 }
762 entry++;
763 }
764
765 res.unlock();
766
767 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000768 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 uint32_t ref = ident;
772 if (resolve) {
773 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800774#if THROW_ON_BAD_ID
775 if (block == BAD_INDEX) {
776 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
777 return 0;
778 }
779#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000781 if (block >= 0) {
782 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
783 }
784
785 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786}
787
788static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
789{
790 AssetManager* am = assetManagerForJavaObject(env, clazz);
791 if (am == NULL) {
792 return 0;
793 }
794 return am->getResources().getTableCount();
795}
796
Ashok Bhat896043d2014-01-17 16:02:38 +0000797static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 jint block)
799{
800 AssetManager* am = assetManagerForJavaObject(env, clazz);
801 if (am == NULL) {
802 return 0;
803 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000804 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805}
806
807static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
808 jint cookie)
809{
810 AssetManager* am = assetManagerForJavaObject(env, clazz);
811 if (am == NULL) {
812 return NULL;
813 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000814 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700816 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 return NULL;
818 }
819 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 return str;
821}
822
Ashok Bhat896043d2014-01-17 16:02:38 +0000823static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824{
825 AssetManager* am = assetManagerForJavaObject(env, clazz);
826 if (am == NULL) {
827 return 0;
828 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000829 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830}
831
832static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000833 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834{
Ashok Bhat896043d2014-01-17 16:02:38 +0000835 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 delete theme;
837}
838
839static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000840 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 jint styleRes,
842 jboolean force)
843{
Ashok Bhat896043d2014-01-17 16:02:38 +0000844 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800845 theme->applyStyle(styleRes, force ? true : false);
846}
847
848static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000849 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850{
Ashok Bhat896043d2014-01-17 16:02:38 +0000851 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
852 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 dest->setTo(*src);
854}
855
856static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000857 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858{
Ashok Bhat896043d2014-01-17 16:02:38 +0000859 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 const ResTable& res(theme->getResTable());
861
862 Res_value value;
863 // XXX value could be different in different configs!
864 uint32_t typeSpecFlags = 0;
865 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
866 uint32_t ref = 0;
867 if (resolve) {
868 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800869#if THROW_ON_BAD_ID
870 if (block == BAD_INDEX) {
871 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
872 return 0;
873 }
874#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 }
876 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
877}
878
879static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000880 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 jstring tag, jstring prefix)
882{
Ashok Bhat896043d2014-01-17 16:02:38 +0000883 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 const ResTable& res(theme->getResTable());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886 // XXX Need to use params.
887 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888}
889
890static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000891 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 jint defStyleAttr,
893 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +0000894 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 jintArray attrs,
896 jintArray outValues,
897 jintArray outIndices)
898{
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700899 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700900 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700901 return JNI_FALSE;
902 }
903 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700904 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700905 return JNI_FALSE;
906 }
907 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700908 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 return JNI_FALSE;
910 }
911
Dianne Hackbornb8d81672009-11-20 14:26:42 -0800912 DEBUG_STYLES(LOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
913 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700914
Ashok Bhat896043d2014-01-17 16:02:38 +0000915 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +0000917 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700918 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919 Res_value value;
920
921 const jsize NI = env->GetArrayLength(attrs);
922 const jsize NV = env->GetArrayLength(outValues);
923 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700924 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 return JNI_FALSE;
926 }
927
928 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
929 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 return JNI_FALSE;
931 }
932
933 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
934 jint* dest = baseDest;
935 if (dest == NULL) {
936 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 return JNI_FALSE;
938 }
939
940 jint* indices = NULL;
941 int indicesIdx = 0;
942 if (outIndices != NULL) {
943 if (env->GetArrayLength(outIndices) > NI) {
944 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
945 }
946 }
947
948 // Load default style from attribute, if specified...
949 uint32_t defStyleBagTypeSetFlags = 0;
950 if (defStyleAttr != 0) {
951 Res_value value;
952 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
953 if (value.dataType == Res_value::TYPE_REFERENCE) {
954 defStyleRes = value.data;
955 }
956 }
957 }
958
959 // Retrieve the style class associated with the current XML tag.
960 int style = 0;
961 uint32_t styleBagTypeSetFlags = 0;
962 if (xmlParser != NULL) {
963 ssize_t idx = xmlParser->indexOfStyle();
964 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
965 if (value.dataType == value.TYPE_ATTRIBUTE) {
966 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
967 value.dataType = Res_value::TYPE_NULL;
968 }
969 }
970 if (value.dataType == value.TYPE_REFERENCE) {
971 style = value.data;
972 }
973 }
974 }
975
976 // Now lock down the resource object and start pulling stuff from it.
977 res.lock();
978
979 // Retrieve the default style bag, if requested.
980 const ResTable::bag_entry* defStyleEnt = NULL;
981 uint32_t defStyleTypeSetFlags = 0;
982 ssize_t bagOff = defStyleRes != 0
983 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
984 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
985 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
986 (bagOff >= 0 ? bagOff : 0);
987
988 // Retrieve the style class bag, if requested.
989 const ResTable::bag_entry* styleEnt = NULL;
990 uint32_t styleTypeSetFlags = 0;
991 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
992 styleTypeSetFlags |= styleBagTypeSetFlags;
993 const ResTable::bag_entry* endStyleEnt = styleEnt +
994 (bagOff >= 0 ? bagOff : 0);
995
996 // Retrieve the XML attributes, if requested.
997 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
998 jsize ix=0;
999 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1000
1001 static const ssize_t kXmlBlock = 0x10000000;
1002
1003 // Now iterate through all of the attributes that the client has requested,
1004 // filling in each with whatever data we can find.
1005 ssize_t block = 0;
1006 uint32_t typeSetFlags;
1007 for (jsize ii=0; ii<NI; ii++) {
1008 const uint32_t curIdent = (uint32_t)src[ii];
1009
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001010 DEBUG_STYLES(LOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 // Try to find a value for this attribute... we prioritize values
1013 // coming from, first XML attributes, then XML style, then default
1014 // style, and finally the theme.
1015 value.dataType = Res_value::TYPE_NULL;
1016 value.data = 0;
1017 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001018 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019
1020 // Skip through XML attributes until the end or the next possible match.
1021 while (ix < NX && curIdent > curXmlAttr) {
1022 ix++;
1023 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1024 }
1025 // Retrieve the current XML attribute if it matches, and step to next.
1026 if (ix < NX && curIdent == curXmlAttr) {
1027 block = kXmlBlock;
1028 xmlParser->getAttributeValue(ix, &value);
1029 ix++;
1030 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001031 DEBUG_STYLES(LOGI("-> From XML: type=0x%x, data=0x%08x",
1032 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
1034
1035 // Skip through the style values until the end or the next possible match.
1036 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
1037 styleEnt++;
1038 }
1039 // Retrieve the current style attribute if it matches, and step to next.
1040 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1041 if (value.dataType == Res_value::TYPE_NULL) {
1042 block = styleEnt->stringBlock;
1043 typeSetFlags = styleTypeSetFlags;
1044 value = styleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001045 DEBUG_STYLES(LOGI("-> From style: type=0x%x, data=0x%08x",
1046 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 }
1048 styleEnt++;
1049 }
1050
1051 // Skip through the default style values until the end or the next possible match.
1052 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1053 defStyleEnt++;
1054 }
1055 // Retrieve the current default style attribute if it matches, and step to next.
1056 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1057 if (value.dataType == Res_value::TYPE_NULL) {
1058 block = defStyleEnt->stringBlock;
1059 typeSetFlags = defStyleTypeSetFlags;
1060 value = defStyleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001061 DEBUG_STYLES(LOGI("-> From def style: type=0x%x, data=0x%08x",
1062 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
1064 defStyleEnt++;
1065 }
1066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 uint32_t resid = 0;
1068 if (value.dataType != Res_value::TYPE_NULL) {
1069 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001070 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1071 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001073 DEBUG_STYLES(LOGI("-> Resolved attr: type=0x%x, data=0x%08x",
1074 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 } else {
1076 // If we still don't have a value for this attribute, try to find
1077 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1079 if (newBlock >= 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001080 DEBUG_STYLES(LOGI("-> From theme: type=0x%x, data=0x%08x",
1081 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001082 newBlock = res.resolveReference(&value, block, &resid,
1083 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001084#if THROW_ON_BAD_ID
1085 if (newBlock == BAD_INDEX) {
1086 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1087 return JNI_FALSE;
1088 }
1089#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001091 DEBUG_STYLES(LOGI("-> Resolved theme: type=0x%x, data=0x%08x",
1092 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 }
1094 }
1095
1096 // Deal with the special @null value -- it turns back to TYPE_NULL.
1097 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001098 DEBUG_STYLES(LOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001100 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 }
1102
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001103 DEBUG_STYLES(LOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
1104 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105
1106 // Write the final value back to Java.
1107 dest[STYLE_TYPE] = value.dataType;
1108 dest[STYLE_DATA] = value.data;
1109 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001110 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 dest[STYLE_RESOURCE_ID] = resid;
1112 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001113 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1116 indicesIdx++;
1117 indices[indicesIdx] = ii;
1118 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 dest += STYLE_NUM_ENTRIES;
1121 }
1122
1123 res.unlock();
1124
1125 if (indices != NULL) {
1126 indices[0] = indicesIdx;
1127 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1128 }
1129 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1130 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1131
1132 return JNI_TRUE;
1133}
1134
1135static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001136 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 jintArray attrs,
1138 jintArray outValues,
1139 jintArray outIndices)
1140{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001141 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001142 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001143 return JNI_FALSE;
1144 }
1145 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001146 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001147 return JNI_FALSE;
1148 }
1149 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001150 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 return JNI_FALSE;
1152 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 AssetManager* am = assetManagerForJavaObject(env, clazz);
1155 if (am == NULL) {
1156 return JNI_FALSE;
1157 }
1158 const ResTable& res(am->getResources());
1159 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001160 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 const jsize NI = env->GetArrayLength(attrs);
1164 const jsize NV = env->GetArrayLength(outValues);
1165 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001166 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 return JNI_FALSE;
1168 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1171 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 return JNI_FALSE;
1173 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1176 jint* dest = baseDest;
1177 if (dest == NULL) {
1178 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 return JNI_FALSE;
1180 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 jint* indices = NULL;
1183 int indicesIdx = 0;
1184 if (outIndices != NULL) {
1185 if (env->GetArrayLength(outIndices) > NI) {
1186 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1187 }
1188 }
1189
1190 // Now lock down the resource object and start pulling stuff from it.
1191 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 // Retrieve the XML attributes, if requested.
1194 const jsize NX = xmlParser->getAttributeCount();
1195 jsize ix=0;
1196 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 // Now iterate through all of the attributes that the client has requested,
1201 // filling in each with whatever data we can find.
1202 ssize_t block = 0;
1203 uint32_t typeSetFlags;
1204 for (jsize ii=0; ii<NI; ii++) {
1205 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 // Try to find a value for this attribute...
1208 value.dataType = Res_value::TYPE_NULL;
1209 value.data = 0;
1210 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001211 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 // Skip through XML attributes until the end or the next possible match.
1214 while (ix < NX && curIdent > curXmlAttr) {
1215 ix++;
1216 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1217 }
1218 // Retrieve the current XML attribute if it matches, and step to next.
1219 if (ix < NX && curIdent == curXmlAttr) {
1220 block = kXmlBlock;
1221 xmlParser->getAttributeValue(ix, &value);
1222 ix++;
1223 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1224 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1227 uint32_t resid = 0;
1228 if (value.dataType != Res_value::TYPE_NULL) {
1229 // Take care of resolving the found resource to its final value.
1230 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001231 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1232 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001233#if THROW_ON_BAD_ID
1234 if (newBlock == BAD_INDEX) {
1235 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1236 return JNI_FALSE;
1237 }
1238#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 if (newBlock >= 0) block = newBlock;
1240 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 // Deal with the special @null value -- it turns back to TYPE_NULL.
1243 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1244 value.dataType = Res_value::TYPE_NULL;
1245 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 // Write the final value back to Java.
1250 dest[STYLE_TYPE] = value.dataType;
1251 dest[STYLE_DATA] = value.data;
1252 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001253 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 dest[STYLE_RESOURCE_ID] = resid;
1255 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001256 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1259 indicesIdx++;
1260 indices[indicesIdx] = ii;
1261 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 dest += STYLE_NUM_ENTRIES;
1264 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 if (indices != NULL) {
1269 indices[0] = indicesIdx;
1270 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1271 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1274 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 return JNI_TRUE;
1277}
1278
1279static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1280 jint id)
1281{
1282 AssetManager* am = assetManagerForJavaObject(env, clazz);
1283 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001284 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 }
1286 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 res.lock();
1289 const ResTable::bag_entry* defStyleEnt = NULL;
1290 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1291 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001292
Ashok Bhat896043d2014-01-17 16:02:38 +00001293 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294}
1295
1296static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1297 jint id,
1298 jintArray outValues)
1299{
1300 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001301 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 return JNI_FALSE;
1303 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305 AssetManager* am = assetManagerForJavaObject(env, clazz);
1306 if (am == NULL) {
1307 return JNI_FALSE;
1308 }
1309 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001310 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 Res_value value;
1312 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1317 jint* dest = baseDest;
1318 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001319 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 return JNI_FALSE;
1321 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 // Now lock down the resource object and start pulling stuff from it.
1324 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 const ResTable::bag_entry* arrayEnt = NULL;
1327 uint32_t arrayTypeSetFlags = 0;
1328 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1329 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1330 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 int i = 0;
1333 uint32_t typeSetFlags;
1334 while (i < NV && arrayEnt < endArrayEnt) {
1335 block = arrayEnt->stringBlock;
1336 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001337 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 uint32_t resid = 0;
1341 if (value.dataType != Res_value::TYPE_NULL) {
1342 // Take care of resolving the found resource to its final value.
1343 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001344 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1345 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001346#if THROW_ON_BAD_ID
1347 if (newBlock == BAD_INDEX) {
1348 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1349 return JNI_FALSE;
1350 }
1351#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 if (newBlock >= 0) block = newBlock;
1353 }
1354
1355 // Deal with the special @null value -- it turns back to TYPE_NULL.
1356 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1357 value.dataType = Res_value::TYPE_NULL;
1358 }
1359
1360 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1361
1362 // Write the final value back to Java.
1363 dest[STYLE_TYPE] = value.dataType;
1364 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001365 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 dest[STYLE_RESOURCE_ID] = resid;
1367 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001368 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 dest += STYLE_NUM_ENTRIES;
1370 i+= STYLE_NUM_ENTRIES;
1371 arrayEnt++;
1372 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001376 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 return i;
1381}
1382
Ashok Bhat896043d2014-01-17 16:02:38 +00001383static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 jint cookie,
1385 jstring fileName)
1386{
1387 AssetManager* am = assetManagerForJavaObject(env, clazz);
1388 if (am == NULL) {
1389 return 0;
1390 }
1391
Steve Block71f2cf12011-10-20 11:56:00 +01001392 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393
Elliott Hughes69a017b2011-04-08 14:10:28 -07001394 ScopedUtfChars fileName8(env, fileName);
1395 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 return 0;
1397 }
1398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +00001400 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_BUFFER)
Elliott Hughes69a017b2011-04-08 14:10:28 -07001401 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402
1403 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001404 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 return 0;
1406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
1408 ResXMLTree* block = new ResXMLTree();
1409 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1410 a->close();
1411 delete a;
1412
1413 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001414 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 return 0;
1416 }
1417
Ashok Bhat896043d2014-01-17 16:02:38 +00001418 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419}
1420
1421static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1422 jint arrayResId)
1423{
1424 AssetManager* am = assetManagerForJavaObject(env, clazz);
1425 if (am == NULL) {
1426 return NULL;
1427 }
1428 const ResTable& res(am->getResources());
1429
1430 const ResTable::bag_entry* startOfBag;
1431 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1432 if (N < 0) {
1433 return NULL;
1434 }
1435
1436 jintArray array = env->NewIntArray(N * 2);
1437 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 res.unlockBag(startOfBag);
1439 return NULL;
1440 }
1441
1442 Res_value value;
1443 const ResTable::bag_entry* bag = startOfBag;
1444 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1445 jint stringIndex = -1;
1446 jint stringBlock = 0;
1447 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 // Take care of resolving the found resource to its final value.
1450 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1451 if (value.dataType == Res_value::TYPE_STRING) {
1452 stringIndex = value.data;
1453 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001454
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001455#if THROW_ON_BAD_ID
1456 if (stringBlock == BAD_INDEX) {
1457 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1458 return array;
1459 }
1460#endif
Elliott Hughes69a017b2011-04-08 14:10:28 -07001461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 //todo: It might be faster to allocate a C array to contain
1463 // the blocknums and indices, put them in there and then
1464 // do just one SetIntArrayRegion()
1465 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1466 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1467 j = j + 2;
1468 }
1469 res.unlockBag(startOfBag);
1470 return array;
1471}
1472
1473static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1474 jint arrayResId)
1475{
1476 AssetManager* am = assetManagerForJavaObject(env, clazz);
1477 if (am == NULL) {
1478 return NULL;
1479 }
1480 const ResTable& res(am->getResources());
1481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 const ResTable::bag_entry* startOfBag;
1483 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1484 if (N < 0) {
1485 return NULL;
1486 }
1487
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001488 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001489 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 res.unlockBag(startOfBag);
1491 return NULL;
1492 }
1493
1494 Res_value value;
1495 const ResTable::bag_entry* bag = startOfBag;
1496 size_t strLen = 0;
1497 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1498 value = bag->map.value;
1499 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 // Take care of resolving the found resource to its final value.
1502 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001503#if THROW_ON_BAD_ID
1504 if (block == BAD_INDEX) {
1505 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1506 return array;
1507 }
1508#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001510 const ResStringPool* pool = res.getTableStringBlock(block);
1511 const char* str8 = pool->string8At(value.data, &strLen);
1512 if (str8 != NULL) {
1513 str = env->NewStringUTF(str8);
1514 } else {
1515 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1516 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001517 }
1518
1519 // If one of our NewString{UTF} calls failed due to memory, an
1520 // exception will be pending.
1521 if (env->ExceptionCheck()) {
1522 res.unlockBag(startOfBag);
1523 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 }
Kenny Root780d2a12010-02-22 22:36:26 -08001525
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001526 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001527
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001528 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1529 // If we have a large amount of strings in our array, we might
1530 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001531 env->DeleteLocalRef(str);
1532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
1534 res.unlockBag(startOfBag);
1535 return array;
1536}
1537
1538static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1539 jint arrayResId)
1540{
1541 AssetManager* am = assetManagerForJavaObject(env, clazz);
1542 if (am == NULL) {
1543 return NULL;
1544 }
1545 const ResTable& res(am->getResources());
1546
1547 const ResTable::bag_entry* startOfBag;
1548 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1549 if (N < 0) {
1550 return NULL;
1551 }
1552
1553 jintArray array = env->NewIntArray(N);
1554 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 res.unlockBag(startOfBag);
1556 return NULL;
1557 }
1558
1559 Res_value value;
1560 const ResTable::bag_entry* bag = startOfBag;
1561 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1562 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 // Take care of resolving the found resource to its final value.
1565 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001566#if THROW_ON_BAD_ID
1567 if (block == BAD_INDEX) {
1568 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1569 return array;
1570 }
1571#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 if (value.dataType >= Res_value::TYPE_FIRST_INT
1573 && value.dataType <= Res_value::TYPE_LAST_INT) {
1574 int intVal = value.data;
1575 env->SetIntArrayRegion(array, i, 1, &intVal);
1576 }
1577 }
1578 res.unlockBag(startOfBag);
1579 return array;
1580}
1581
1582static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)
1583{
1584 AssetManager* am = new AssetManager();
1585 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001586 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 return;
1588 }
1589
1590 am->addDefaultAssets();
1591
Steve Block71f2cf12011-10-20 11:56:00 +01001592 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001593 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594}
1595
1596static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1597{
1598 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001599 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001600 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 if (am != NULL) {
1602 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001603 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 }
1605}
1606
1607static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1608{
1609 return Asset::getGlobalCount();
1610}
1611
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001612static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1613{
1614 String8 alloc = Asset::getAssetAllocations();
1615 if (alloc.length() <= 0) {
1616 return NULL;
1617 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001618
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001619 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001620 return str;
1621}
1622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1624{
1625 return AssetManager::getGlobalCount();
1626}
1627
1628// ----------------------------------------------------------------------------
1629
1630/*
1631 * JNI registration.
1632 */
1633static JNINativeMethod gAssetManagerMethods[] = {
1634 /* name, signature, funcPtr */
1635
1636 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00001637 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 (void*) android_content_AssetManager_openAsset },
1639 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1640 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00001641 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 (void*) android_content_AssetManager_openNonAssetNative },
1643 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1644 (void*) android_content_AssetManager_openNonAssetFdNative },
1645 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1646 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00001647 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001649 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00001651 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001653 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001655 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00001657 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07001659 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 (void*) android_content_AssetManager_addAssetPath },
1661 { "isUpToDate", "()Z",
1662 (void*) android_content_AssetManager_isUpToDate },
1663
1664 // Resources.
1665 { "setLocale", "(Ljava/lang/String;)V",
1666 (void*) android_content_AssetManager_setLocale },
1667 { "getLocales", "()[Ljava/lang/String;",
1668 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001669 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 (void*) android_content_AssetManager_setConfiguration },
1671 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
1672 (void*) android_content_AssetManager_getResourceIdentifier },
1673 { "getResourceName","(I)Ljava/lang/String;",
1674 (void*) android_content_AssetManager_getResourceName },
1675 { "getResourcePackageName","(I)Ljava/lang/String;",
1676 (void*) android_content_AssetManager_getResourcePackageName },
1677 { "getResourceTypeName","(I)Ljava/lang/String;",
1678 (void*) android_content_AssetManager_getResourceTypeName },
1679 { "getResourceEntryName","(I)Ljava/lang/String;",
1680 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07001681 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 (void*) android_content_AssetManager_loadResourceValue },
1683 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
1684 (void*) android_content_AssetManager_loadResourceBagValue },
1685 { "getStringBlockCount","()I",
1686 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00001687 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 (void*) android_content_AssetManager_getNativeStringBlock },
1689 { "getCookieName","(I)Ljava/lang/String;",
1690 (void*) android_content_AssetManager_getCookieName },
1691
1692 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00001693 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001695 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001697 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00001699 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001701 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00001703 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001705 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 (void*) android_content_AssetManager_applyStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00001707 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 (void*) android_content_AssetManager_retrieveAttributes },
1709 { "getArraySize","(I)I",
1710 (void*) android_content_AssetManager_getArraySize },
1711 { "retrieveArray","(I[I)I",
1712 (void*) android_content_AssetManager_retrieveArray },
1713
1714 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00001715 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 (void*) android_content_AssetManager_openXmlAssetNative },
1717
1718 // Arrays.
1719 { "getArrayStringResource","(I)[Ljava/lang/String;",
1720 (void*) android_content_AssetManager_getArrayStringResource },
1721 { "getArrayStringInfo","(I)[I",
1722 (void*) android_content_AssetManager_getArrayStringInfo },
1723 { "getArrayIntResource","(I)[I",
1724 (void*) android_content_AssetManager_getArrayIntResource },
1725
1726 // Bookkeeping.
1727 { "init", "()V",
1728 (void*) android_content_AssetManager_init },
1729 { "destroy", "()V",
1730 (void*) android_content_AssetManager_destroy },
1731 { "getGlobalAssetCount", "()I",
1732 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001733 { "getAssetAllocations", "()Ljava/lang/String;",
1734 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 { "getGlobalAssetManagerCount", "()I",
1736 (void*) android_content_AssetManager_getGlobalAssetCount },
1737};
1738
1739int register_android_content_AssetManager(JNIEnv* env)
1740{
1741 jclass typedValue = env->FindClass("android/util/TypedValue");
1742 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
1743 gTypedValueOffsets.mType
1744 = env->GetFieldID(typedValue, "type", "I");
1745 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
1746 gTypedValueOffsets.mData
1747 = env->GetFieldID(typedValue, "data", "I");
1748 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
1749 gTypedValueOffsets.mString
1750 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
1751 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
1752 gTypedValueOffsets.mAssetCookie
1753 = env->GetFieldID(typedValue, "assetCookie", "I");
1754 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
1755 gTypedValueOffsets.mResourceId
1756 = env->GetFieldID(typedValue, "resourceId", "I");
1757 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
1758 gTypedValueOffsets.mChangingConfigurations
1759 = env->GetFieldID(typedValue, "changingConfigurations", "I");
1760 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
1761 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
1762 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
1763
1764 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
1765 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
1766 gAssetFileDescriptorOffsets.mFd
1767 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
1768 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
1769 gAssetFileDescriptorOffsets.mStartOffset
1770 = env->GetFieldID(assetFd, "mStartOffset", "J");
1771 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
1772 gAssetFileDescriptorOffsets.mLength
1773 = env->GetFieldID(assetFd, "mLength", "J");
1774 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
1775
1776 jclass assetManager = env->FindClass("android/content/res/AssetManager");
1777 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
1778 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00001779 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
1781
Carl Shapiroc1318ba2011-03-03 14:22:28 -08001782 jclass stringClass = env->FindClass("java/lang/String");
1783 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
1784 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001785 LOG_FATAL_IF(g_stringClass == NULL, "Unable to create global reference for class java/lang/String");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786
1787 return AndroidRuntime::registerNativeMethods(env,
1788 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
1789}
1790
1791}; // namespace android