blob: 2884077f8436212e54d88e7d454ff81f9e3b03da [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
Dan Albert66987492014-11-20 11:41:21 -0800655 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
656 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
657 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 jsize defTypeLen = defType
659 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800660 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
661 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
662 NULL))
663 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 jsize defPackageLen = defPackage
665 ? env->GetStringLength(defPackage) : 0;
666
667 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800668 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
669 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800672 env->ReleaseStringChars(defPackage,
673 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 }
675 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800676 env->ReleaseStringChars(defType,
677 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 return ident;
681}
682
683static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
684 jint resid)
685{
686 AssetManager* am = assetManagerForJavaObject(env, clazz);
687 if (am == NULL) {
688 return NULL;
689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700692 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 return NULL;
694 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 String16 str;
697 if (name.package != NULL) {
698 str.setTo(name.package, name.packageLen);
699 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700700 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 if (str.size() > 0) {
702 char16_t div = ':';
703 str.append(&div, 1);
704 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700705 if (name.type8 != NULL) {
706 str.append(String16(name.type8, name.typeLen));
707 } else {
708 str.append(name.type, name.typeLen);
709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700711 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 if (str.size() > 0) {
713 char16_t div = '/';
714 str.append(&div, 1);
715 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700716 if (name.name8 != NULL) {
717 str.append(String16(name.name8, name.nameLen));
718 } else {
719 str.append(name.name, name.nameLen);
720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 return env->NewString((const jchar*)str.string(), str.size());
724}
725
726static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
727 jint resid)
728{
729 AssetManager* am = assetManagerForJavaObject(env, clazz);
730 if (am == NULL) {
731 return NULL;
732 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700735 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 return NULL;
737 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 if (name.package != NULL) {
740 return env->NewString((const jchar*)name.package, name.packageLen);
741 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 return NULL;
744}
745
746static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
747 jint resid)
748{
749 AssetManager* am = assetManagerForJavaObject(env, clazz);
750 if (am == NULL) {
751 return NULL;
752 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700755 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 return NULL;
757 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700758
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700759 if (name.type8 != NULL) {
760 return env->NewStringUTF(name.type8);
761 }
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 if (name.type != NULL) {
764 return env->NewString((const jchar*)name.type, name.typeLen);
765 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 return NULL;
768}
769
770static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
771 jint resid)
772{
773 AssetManager* am = assetManagerForJavaObject(env, clazz);
774 if (am == NULL) {
775 return NULL;
776 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700779 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 return NULL;
781 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700782
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700783 if (name.name8 != NULL) {
784 return env->NewStringUTF(name.name8);
785 }
786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 if (name.name != NULL) {
788 return env->NewString((const jchar*)name.name, name.nameLen);
789 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 return NULL;
792}
793
794static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
795 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700796 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 jobject outValue,
798 jboolean resolve)
799{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800800 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800801 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700802 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 AssetManager* am = assetManagerForJavaObject(env, clazz);
805 if (am == NULL) {
806 return 0;
807 }
808 const ResTable& res(am->getResources());
809
810 Res_value value;
811 ResTable_config config;
812 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700813 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800814 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800815 if (block == BAD_INDEX) {
816 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
817 return 0;
818 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800819 }
820 uint32_t ref = ident;
821 if (resolve) {
822 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
823 if (kThrowOnBadId) {
824 if (block == BAD_INDEX) {
825 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
826 return 0;
827 }
828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000830 if (block >= 0) {
831 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
832 }
833
834 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835}
836
837static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
838 jint ident, jint bagEntryId,
839 jobject outValue, jboolean resolve)
840{
841 AssetManager* am = assetManagerForJavaObject(env, clazz);
842 if (am == NULL) {
843 return 0;
844 }
845 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 // Now lock down the resource object and start pulling stuff from it.
848 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 ssize_t block = -1;
851 Res_value value;
852
853 const ResTable::bag_entry* entry = NULL;
854 uint32_t typeSpecFlags;
855 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
856
857 for (ssize_t i=0; i<entryCount; i++) {
858 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
859 block = entry->stringBlock;
860 value = entry->map.value;
861 }
862 entry++;
863 }
864
865 res.unlock();
866
867 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000868 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 uint32_t ref = ident;
872 if (resolve) {
873 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800874 if (kThrowOnBadId) {
875 if (block == BAD_INDEX) {
876 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
877 return 0;
878 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000881 if (block >= 0) {
882 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
883 }
884
885 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886}
887
888static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
889{
890 AssetManager* am = assetManagerForJavaObject(env, clazz);
891 if (am == NULL) {
892 return 0;
893 }
894 return am->getResources().getTableCount();
895}
896
Ashok Bhat896043d2014-01-17 16:02:38 +0000897static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 jint block)
899{
900 AssetManager* am = assetManagerForJavaObject(env, clazz);
901 if (am == NULL) {
902 return 0;
903 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000904 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905}
906
907static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
908 jint cookie)
909{
910 AssetManager* am = assetManagerForJavaObject(env, clazz);
911 if (am == NULL) {
912 return NULL;
913 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000914 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700916 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 return NULL;
918 }
919 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 return str;
921}
922
Adam Lesinskide898ff2014-01-29 18:20:45 -0800923static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
924{
925 AssetManager* am = assetManagerForJavaObject(env, clazz);
926 if (am == NULL) {
927 return 0;
928 }
929
930 const ResTable& res = am->getResources();
931
932 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
933 gSparseArrayOffsets.constructor);
934 const size_t N = res.getBasePackageCount();
935 for (size_t i = 0; i < N; i++) {
936 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -0800937 env->CallVoidMethod(
938 sparseArray, gSparseArrayOffsets.put,
939 static_cast<jint>(res.getBasePackageId(i)),
940 env->NewString(reinterpret_cast<const jchar*>(name.string()),
941 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -0800942 }
943 return sparseArray;
944}
945
Ashok Bhat896043d2014-01-17 16:02:38 +0000946static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
948 AssetManager* am = assetManagerForJavaObject(env, clazz);
949 if (am == NULL) {
950 return 0;
951 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000952 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953}
954
955static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000956 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957{
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 delete theme;
960}
961
962static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 jint styleRes,
965 jboolean force)
966{
Ashok Bhat896043d2014-01-17 16:02:38 +0000967 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 theme->applyStyle(styleRes, force ? true : false);
969}
970
971static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000972 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973{
Ashok Bhat896043d2014-01-17 16:02:38 +0000974 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
975 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 dest->setTo(*src);
977}
978
979static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000980 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981{
Ashok Bhat896043d2014-01-17 16:02:38 +0000982 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 const ResTable& res(theme->getResTable());
984
985 Res_value value;
986 // XXX value could be different in different configs!
987 uint32_t typeSpecFlags = 0;
988 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
989 uint32_t ref = 0;
990 if (resolve) {
991 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800992 if (kThrowOnBadId) {
993 if (block == BAD_INDEX) {
994 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
995 return 0;
996 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 }
999 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1000}
1001
1002static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001003 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 jstring tag, jstring prefix)
1005{
Ashok Bhat896043d2014-01-17 16:02:38 +00001006 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001008 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 // XXX Need to use params.
1011 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012}
1013
Alan Viverette52b999f2014-03-24 18:00:26 -07001014static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1015 jlong themeToken,
1016 jint defStyleAttr,
1017 jint defStyleRes,
1018 jintArray inValues,
1019 jintArray attrs,
1020 jintArray outValues,
1021 jintArray outIndices)
1022{
1023 if (themeToken == 0) {
1024 jniThrowNullPointerException(env, "theme token");
1025 return JNI_FALSE;
1026 }
1027 if (attrs == NULL) {
1028 jniThrowNullPointerException(env, "attrs");
1029 return JNI_FALSE;
1030 }
1031 if (outValues == NULL) {
1032 jniThrowNullPointerException(env, "out values");
1033 return JNI_FALSE;
1034 }
1035
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001036 if (kDebugStyles) {
1037 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
1038 themeToken, defStyleAttr, defStyleRes);
1039 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001040
1041 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1042 const ResTable& res = theme->getResTable();
1043 ResTable_config config;
1044 Res_value value;
1045
1046 const jsize NI = env->GetArrayLength(attrs);
1047 const jsize NV = env->GetArrayLength(outValues);
1048 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1049 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1050 return JNI_FALSE;
1051 }
1052
1053 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1054 if (src == NULL) {
1055 return JNI_FALSE;
1056 }
1057
1058 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1059 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1060
1061 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1062 jint* dest = baseDest;
1063 if (dest == NULL) {
1064 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1065 return JNI_FALSE;
1066 }
1067
1068 jint* indices = NULL;
1069 int indicesIdx = 0;
1070 if (outIndices != NULL) {
1071 if (env->GetArrayLength(outIndices) > NI) {
1072 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1073 }
1074 }
1075
1076 // Load default style from attribute, if specified...
1077 uint32_t defStyleBagTypeSetFlags = 0;
1078 if (defStyleAttr != 0) {
1079 Res_value value;
1080 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1081 if (value.dataType == Res_value::TYPE_REFERENCE) {
1082 defStyleRes = value.data;
1083 }
1084 }
1085 }
1086
1087 // Now lock down the resource object and start pulling stuff from it.
1088 res.lock();
1089
1090 // Retrieve the default style bag, if requested.
1091 const ResTable::bag_entry* defStyleEnt = NULL;
1092 uint32_t defStyleTypeSetFlags = 0;
1093 ssize_t bagOff = defStyleRes != 0
1094 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1095 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1096 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1097 (bagOff >= 0 ? bagOff : 0);;
1098
1099 // Now iterate through all of the attributes that the client has requested,
1100 // filling in each with whatever data we can find.
1101 ssize_t block = 0;
1102 uint32_t typeSetFlags;
1103 for (jsize ii=0; ii<NI; ii++) {
1104 const uint32_t curIdent = (uint32_t)src[ii];
1105
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001106 if (kDebugStyles) {
1107 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1108 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001109
1110 // Try to find a value for this attribute... we prioritize values
1111 // coming from, first XML attributes, then XML style, then default
1112 // style, and finally the theme.
1113 value.dataType = Res_value::TYPE_NULL;
1114 value.data = 0;
1115 typeSetFlags = 0;
1116 config.density = 0;
1117
1118 // Retrieve the current input value if available.
1119 if (NSV > 0 && srcValues[ii] != 0) {
1120 block = -1;
1121 value.dataType = Res_value::TYPE_ATTRIBUTE;
1122 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001123 if (kDebugStyles) {
1124 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1125 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001126 }
1127
1128 // Skip through the default style values until the end or the next possible match.
1129 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1130 defStyleEnt++;
1131 }
1132 // Retrieve the current default style attribute if it matches, and step to next.
1133 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1134 if (value.dataType == Res_value::TYPE_NULL) {
1135 block = defStyleEnt->stringBlock;
1136 typeSetFlags = defStyleTypeSetFlags;
1137 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001138 if (kDebugStyles) {
1139 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1140 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001141 }
1142 defStyleEnt++;
1143 }
1144
1145 uint32_t resid = 0;
1146 if (value.dataType != Res_value::TYPE_NULL) {
1147 // Take care of resolving the found resource to its final value.
1148 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1149 &resid, &typeSetFlags, &config);
1150 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001151 if (kDebugStyles) {
1152 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1153 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001154 } else {
1155 // If we still don't have a value for this attribute, try to find
1156 // it in the theme!
1157 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1158 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001159 if (kDebugStyles) {
1160 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1161 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001162 newBlock = res.resolveReference(&value, block, &resid,
1163 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001164 if (kThrowOnBadId) {
1165 if (newBlock == BAD_INDEX) {
1166 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1167 return JNI_FALSE;
1168 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001169 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001170 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001171 if (kDebugStyles) {
1172 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1173 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001174 }
1175 }
1176
1177 // Deal with the special @null value -- it turns back to TYPE_NULL.
1178 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001179 if (kDebugStyles) {
1180 ALOGI("-> Setting to @null!");
1181 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001182 value.dataType = Res_value::TYPE_NULL;
1183 block = -1;
1184 }
1185
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001186 if (kDebugStyles) {
1187 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1188 value.data);
1189 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001190
1191 // Write the final value back to Java.
1192 dest[STYLE_TYPE] = value.dataType;
1193 dest[STYLE_DATA] = value.data;
1194 dest[STYLE_ASSET_COOKIE] =
1195 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1196 dest[STYLE_RESOURCE_ID] = resid;
1197 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1198 dest[STYLE_DENSITY] = config.density;
1199
1200 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1201 indicesIdx++;
1202 indices[indicesIdx] = ii;
1203 }
1204
1205 dest += STYLE_NUM_ENTRIES;
1206 }
1207
1208 res.unlock();
1209
1210 if (indices != NULL) {
1211 indices[0] = indicesIdx;
1212 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1213 }
1214 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1215 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1216 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1217
1218 return JNI_TRUE;
1219}
1220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001222 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 jint defStyleAttr,
1224 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001225 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 jintArray attrs,
1227 jintArray outValues,
1228 jintArray outIndices)
1229{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001230 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001231 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001232 return JNI_FALSE;
1233 }
1234 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001235 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001236 return JNI_FALSE;
1237 }
1238 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001239 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 return JNI_FALSE;
1241 }
1242
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001243 if (kDebugStyles) {
1244 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
1245 themeToken, defStyleAttr, defStyleRes, xmlParserToken);
1246 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001247
Ashok Bhat896043d2014-01-17 16:02:38 +00001248 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001250 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001251 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 Res_value value;
1253
1254 const jsize NI = env->GetArrayLength(attrs);
1255 const jsize NV = env->GetArrayLength(outValues);
1256 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001257 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 return JNI_FALSE;
1259 }
1260
1261 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1262 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 return JNI_FALSE;
1264 }
1265
1266 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1267 jint* dest = baseDest;
1268 if (dest == NULL) {
1269 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 return JNI_FALSE;
1271 }
1272
1273 jint* indices = NULL;
1274 int indicesIdx = 0;
1275 if (outIndices != NULL) {
1276 if (env->GetArrayLength(outIndices) > NI) {
1277 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1278 }
1279 }
1280
1281 // Load default style from attribute, if specified...
1282 uint32_t defStyleBagTypeSetFlags = 0;
1283 if (defStyleAttr != 0) {
1284 Res_value value;
1285 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1286 if (value.dataType == Res_value::TYPE_REFERENCE) {
1287 defStyleRes = value.data;
1288 }
1289 }
1290 }
1291
1292 // Retrieve the style class associated with the current XML tag.
1293 int style = 0;
1294 uint32_t styleBagTypeSetFlags = 0;
1295 if (xmlParser != NULL) {
1296 ssize_t idx = xmlParser->indexOfStyle();
1297 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1298 if (value.dataType == value.TYPE_ATTRIBUTE) {
1299 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1300 value.dataType = Res_value::TYPE_NULL;
1301 }
1302 }
1303 if (value.dataType == value.TYPE_REFERENCE) {
1304 style = value.data;
1305 }
1306 }
1307 }
1308
1309 // Now lock down the resource object and start pulling stuff from it.
1310 res.lock();
1311
1312 // Retrieve the default style bag, if requested.
1313 const ResTable::bag_entry* defStyleEnt = NULL;
1314 uint32_t defStyleTypeSetFlags = 0;
1315 ssize_t bagOff = defStyleRes != 0
1316 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1317 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1318 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1319 (bagOff >= 0 ? bagOff : 0);
1320
1321 // Retrieve the style class bag, if requested.
1322 const ResTable::bag_entry* styleEnt = NULL;
1323 uint32_t styleTypeSetFlags = 0;
1324 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1325 styleTypeSetFlags |= styleBagTypeSetFlags;
1326 const ResTable::bag_entry* endStyleEnt = styleEnt +
1327 (bagOff >= 0 ? bagOff : 0);
1328
1329 // Retrieve the XML attributes, if requested.
1330 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1331 jsize ix=0;
1332 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1333
1334 static const ssize_t kXmlBlock = 0x10000000;
1335
1336 // Now iterate through all of the attributes that the client has requested,
1337 // filling in each with whatever data we can find.
1338 ssize_t block = 0;
1339 uint32_t typeSetFlags;
1340 for (jsize ii=0; ii<NI; ii++) {
1341 const uint32_t curIdent = (uint32_t)src[ii];
1342
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001343 if (kDebugStyles) {
1344 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1345 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 // Try to find a value for this attribute... we prioritize values
1348 // coming from, first XML attributes, then XML style, then default
1349 // style, and finally the theme.
1350 value.dataType = Res_value::TYPE_NULL;
1351 value.data = 0;
1352 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001353 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354
1355 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001356 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 ix++;
1358 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1359 }
1360 // Retrieve the current XML attribute if it matches, and step to next.
1361 if (ix < NX && curIdent == curXmlAttr) {
1362 block = kXmlBlock;
1363 xmlParser->getAttributeValue(ix, &value);
1364 ix++;
1365 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001366 if (kDebugStyles) {
1367 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1368 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 }
1370
1371 // Skip through the style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001372 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 styleEnt++;
1374 }
1375 // Retrieve the current style attribute if it matches, and step to next.
1376 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1377 if (value.dataType == Res_value::TYPE_NULL) {
1378 block = styleEnt->stringBlock;
1379 typeSetFlags = styleTypeSetFlags;
1380 value = styleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001381 if (kDebugStyles) {
1382 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385 styleEnt++;
1386 }
1387
1388 // Skip through the default style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001389 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 defStyleEnt++;
1391 }
1392 // Retrieve the current default style attribute if it matches, and step to next.
1393 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1394 if (value.dataType == Res_value::TYPE_NULL) {
1395 block = defStyleEnt->stringBlock;
1396 typeSetFlags = defStyleTypeSetFlags;
1397 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001398 if (kDebugStyles) {
1399 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 }
1402 defStyleEnt++;
1403 }
1404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 uint32_t resid = 0;
1406 if (value.dataType != Res_value::TYPE_NULL) {
1407 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001408 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1409 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001411 if (kDebugStyles) {
1412 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 } else {
1415 // If we still don't have a value for this attribute, try to find
1416 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1418 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001419 if (kDebugStyles) {
1420 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1421 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001422 newBlock = res.resolveReference(&value, block, &resid,
1423 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001424 if (kThrowOnBadId) {
1425 if (newBlock == BAD_INDEX) {
1426 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1427 return JNI_FALSE;
1428 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001431 if (kDebugStyles) {
1432 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
1435 }
1436
1437 // Deal with the special @null value -- it turns back to TYPE_NULL.
1438 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001439 if (kDebugStyles) {
1440 ALOGI("-> Setting to @null!");
1441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001443 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 }
1445
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001446 if (kDebugStyles) {
1447 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449
1450 // Write the final value back to Java.
1451 dest[STYLE_TYPE] = value.dataType;
1452 dest[STYLE_DATA] = value.data;
1453 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001454 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 dest[STYLE_RESOURCE_ID] = resid;
1456 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001457 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1460 indicesIdx++;
1461 indices[indicesIdx] = ii;
1462 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 dest += STYLE_NUM_ENTRIES;
1465 }
1466
1467 res.unlock();
1468
1469 if (indices != NULL) {
1470 indices[0] = indicesIdx;
1471 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1472 }
1473 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1474 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1475
1476 return JNI_TRUE;
1477}
1478
1479static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001480 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 jintArray attrs,
1482 jintArray outValues,
1483 jintArray outIndices)
1484{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001485 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001486 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001487 return JNI_FALSE;
1488 }
1489 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001490 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001491 return JNI_FALSE;
1492 }
1493 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001494 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 return JNI_FALSE;
1496 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 AssetManager* am = assetManagerForJavaObject(env, clazz);
1499 if (am == NULL) {
1500 return JNI_FALSE;
1501 }
1502 const ResTable& res(am->getResources());
1503 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001504 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 const jsize NI = env->GetArrayLength(attrs);
1508 const jsize NV = env->GetArrayLength(outValues);
1509 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001510 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 return JNI_FALSE;
1512 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1515 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 return JNI_FALSE;
1517 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1520 jint* dest = baseDest;
1521 if (dest == NULL) {
1522 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 return JNI_FALSE;
1524 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 jint* indices = NULL;
1527 int indicesIdx = 0;
1528 if (outIndices != NULL) {
1529 if (env->GetArrayLength(outIndices) > NI) {
1530 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1531 }
1532 }
1533
1534 // Now lock down the resource object and start pulling stuff from it.
1535 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 // Retrieve the XML attributes, if requested.
1538 const jsize NX = xmlParser->getAttributeCount();
1539 jsize ix=0;
1540 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 // Now iterate through all of the attributes that the client has requested,
1545 // filling in each with whatever data we can find.
1546 ssize_t block = 0;
1547 uint32_t typeSetFlags;
1548 for (jsize ii=0; ii<NI; ii++) {
1549 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 // Try to find a value for this attribute...
1552 value.dataType = Res_value::TYPE_NULL;
1553 value.data = 0;
1554 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001555 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001558 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 ix++;
1560 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1561 }
1562 // Retrieve the current XML attribute if it matches, and step to next.
1563 if (ix < NX && curIdent == curXmlAttr) {
1564 block = kXmlBlock;
1565 xmlParser->getAttributeValue(ix, &value);
1566 ix++;
1567 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1568 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1571 uint32_t resid = 0;
1572 if (value.dataType != Res_value::TYPE_NULL) {
1573 // Take care of resolving the found resource to its final value.
1574 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001575 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1576 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001577 if (kThrowOnBadId) {
1578 if (newBlock == BAD_INDEX) {
1579 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1580 return JNI_FALSE;
1581 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 if (newBlock >= 0) block = newBlock;
1584 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 // Deal with the special @null value -- it turns back to TYPE_NULL.
1587 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1588 value.dataType = Res_value::TYPE_NULL;
1589 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 // Write the final value back to Java.
1594 dest[STYLE_TYPE] = value.dataType;
1595 dest[STYLE_DATA] = value.data;
1596 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001597 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 dest[STYLE_RESOURCE_ID] = resid;
1599 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001600 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1603 indicesIdx++;
1604 indices[indicesIdx] = ii;
1605 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 dest += STYLE_NUM_ENTRIES;
1608 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 if (indices != NULL) {
1613 indices[0] = indicesIdx;
1614 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1615 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1618 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 return JNI_TRUE;
1621}
1622
1623static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1624 jint id)
1625{
1626 AssetManager* am = assetManagerForJavaObject(env, clazz);
1627 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001628 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 }
1630 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 res.lock();
1633 const ResTable::bag_entry* defStyleEnt = NULL;
1634 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1635 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636
Ashok Bhat896043d2014-01-17 16:02:38 +00001637 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638}
1639
1640static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1641 jint id,
1642 jintArray outValues)
1643{
1644 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001645 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 return JNI_FALSE;
1647 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 AssetManager* am = assetManagerForJavaObject(env, clazz);
1650 if (am == NULL) {
1651 return JNI_FALSE;
1652 }
1653 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001654 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 Res_value value;
1656 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1661 jint* dest = baseDest;
1662 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001663 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 return JNI_FALSE;
1665 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 // Now lock down the resource object and start pulling stuff from it.
1668 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 const ResTable::bag_entry* arrayEnt = NULL;
1671 uint32_t arrayTypeSetFlags = 0;
1672 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1673 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1674 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 int i = 0;
1677 uint32_t typeSetFlags;
1678 while (i < NV && arrayEnt < endArrayEnt) {
1679 block = arrayEnt->stringBlock;
1680 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001681 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 uint32_t resid = 0;
1685 if (value.dataType != Res_value::TYPE_NULL) {
1686 // Take care of resolving the found resource to its final value.
1687 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001688 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1689 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001690 if (kThrowOnBadId) {
1691 if (newBlock == BAD_INDEX) {
1692 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1693 return JNI_FALSE;
1694 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 if (newBlock >= 0) block = newBlock;
1697 }
1698
1699 // Deal with the special @null value -- it turns back to TYPE_NULL.
1700 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1701 value.dataType = Res_value::TYPE_NULL;
1702 }
1703
1704 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1705
1706 // Write the final value back to Java.
1707 dest[STYLE_TYPE] = value.dataType;
1708 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001709 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 dest[STYLE_RESOURCE_ID] = resid;
1711 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001712 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 dest += STYLE_NUM_ENTRIES;
1714 i+= STYLE_NUM_ENTRIES;
1715 arrayEnt++;
1716 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 return i;
1725}
1726
Ashok Bhat896043d2014-01-17 16:02:38 +00001727static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 jint cookie,
1729 jstring fileName)
1730{
1731 AssetManager* am = assetManagerForJavaObject(env, clazz);
1732 if (am == NULL) {
1733 return 0;
1734 }
1735
Steve Block71f2cf12011-10-20 11:56:00 +01001736 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737
Elliott Hughes69a017b2011-04-08 14:10:28 -07001738 ScopedUtfChars fileName8(env, fileName);
1739 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 return 0;
1741 }
1742
Adam Lesinskide898ff2014-01-29 18:20:45 -08001743 int32_t assetCookie = static_cast<int32_t>(cookie);
1744 Asset* a = assetCookie
1745 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1746 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747
1748 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001749 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001750 return 0;
1751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752
Adam Lesinskide898ff2014-01-29 18:20:45 -08001753 const DynamicRefTable* dynamicRefTable =
1754 am->getResources().getDynamicRefTableForCookie(assetCookie);
1755 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1757 a->close();
1758 delete a;
1759
1760 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001761 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 return 0;
1763 }
1764
Ashok Bhat896043d2014-01-17 16:02:38 +00001765 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766}
1767
1768static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1769 jint arrayResId)
1770{
1771 AssetManager* am = assetManagerForJavaObject(env, clazz);
1772 if (am == NULL) {
1773 return NULL;
1774 }
1775 const ResTable& res(am->getResources());
1776
1777 const ResTable::bag_entry* startOfBag;
1778 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1779 if (N < 0) {
1780 return NULL;
1781 }
1782
1783 jintArray array = env->NewIntArray(N * 2);
1784 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 res.unlockBag(startOfBag);
1786 return NULL;
1787 }
1788
1789 Res_value value;
1790 const ResTable::bag_entry* bag = startOfBag;
1791 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1792 jint stringIndex = -1;
1793 jint stringBlock = 0;
1794 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 // Take care of resolving the found resource to its final value.
1797 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1798 if (value.dataType == Res_value::TYPE_STRING) {
1799 stringIndex = value.data;
1800 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001801
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001802 if (kThrowOnBadId) {
1803 if (stringBlock == BAD_INDEX) {
1804 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1805 return array;
1806 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001807 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 //todo: It might be faster to allocate a C array to contain
1810 // the blocknums and indices, put them in there and then
1811 // do just one SetIntArrayRegion()
1812 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1813 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1814 j = j + 2;
1815 }
1816 res.unlockBag(startOfBag);
1817 return array;
1818}
1819
1820static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1821 jint arrayResId)
1822{
1823 AssetManager* am = assetManagerForJavaObject(env, clazz);
1824 if (am == NULL) {
1825 return NULL;
1826 }
1827 const ResTable& res(am->getResources());
1828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 const ResTable::bag_entry* startOfBag;
1830 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1831 if (N < 0) {
1832 return NULL;
1833 }
1834
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001835 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001836 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 res.unlockBag(startOfBag);
1838 return NULL;
1839 }
1840
1841 Res_value value;
1842 const ResTable::bag_entry* bag = startOfBag;
1843 size_t strLen = 0;
1844 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1845 value = bag->map.value;
1846 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 // Take care of resolving the found resource to its final value.
1849 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001850 if (kThrowOnBadId) {
1851 if (block == BAD_INDEX) {
1852 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1853 return array;
1854 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001857 const ResStringPool* pool = res.getTableStringBlock(block);
1858 const char* str8 = pool->string8At(value.data, &strLen);
1859 if (str8 != NULL) {
1860 str = env->NewStringUTF(str8);
1861 } else {
1862 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001863 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1864 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001865 }
1866
1867 // If one of our NewString{UTF} calls failed due to memory, an
1868 // exception will be pending.
1869 if (env->ExceptionCheck()) {
1870 res.unlockBag(startOfBag);
1871 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 }
Kenny Root780d2a12010-02-22 22:36:26 -08001873
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001874 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001875
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001876 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1877 // If we have a large amount of strings in our array, we might
1878 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001879 env->DeleteLocalRef(str);
1880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 }
1882 res.unlockBag(startOfBag);
1883 return array;
1884}
1885
1886static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1887 jint arrayResId)
1888{
1889 AssetManager* am = assetManagerForJavaObject(env, clazz);
1890 if (am == NULL) {
1891 return NULL;
1892 }
1893 const ResTable& res(am->getResources());
1894
1895 const ResTable::bag_entry* startOfBag;
1896 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1897 if (N < 0) {
1898 return NULL;
1899 }
1900
1901 jintArray array = env->NewIntArray(N);
1902 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 res.unlockBag(startOfBag);
1904 return NULL;
1905 }
1906
1907 Res_value value;
1908 const ResTable::bag_entry* bag = startOfBag;
1909 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1910 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 // Take care of resolving the found resource to its final value.
1913 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001914 if (kThrowOnBadId) {
1915 if (block == BAD_INDEX) {
1916 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1917 return array;
1918 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 if (value.dataType >= Res_value::TYPE_FIRST_INT
1921 && value.dataType <= Res_value::TYPE_LAST_INT) {
1922 int intVal = value.data;
1923 env->SetIntArrayRegion(array, i, 1, &intVal);
1924 }
1925 }
1926 res.unlockBag(startOfBag);
1927 return array;
1928}
1929
Jon Miranda042ad632014-09-03 17:57:35 -07001930static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1931 jint styleId)
1932{
1933 AssetManager* am = assetManagerForJavaObject(env, clazz);
1934 if (am == NULL) {
1935 return NULL;
1936 }
1937 const ResTable& res(am->getResources());
1938
1939 const ResTable::bag_entry* startOfBag;
1940 const ssize_t N = res.lockBag(styleId, &startOfBag);
1941 if (N < 0) {
1942 return NULL;
1943 }
1944
1945 jintArray array = env->NewIntArray(N);
1946 if (array == NULL) {
1947 res.unlockBag(startOfBag);
1948 return NULL;
1949 }
1950
Jon Miranda042ad632014-09-03 17:57:35 -07001951 const ResTable::bag_entry* bag = startOfBag;
1952 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1953 int resourceId = bag->map.name.ident;
1954 env->SetIntArrayRegion(array, i, 1, &resourceId);
1955 }
1956 res.unlockBag(startOfBag);
1957 return array;
1958}
1959
Mårten Kongstad48d22322014-01-31 14:43:27 +01001960static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001962 if (isSystem) {
1963 verifySystemIdmaps();
1964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 AssetManager* am = new AssetManager();
1966 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001967 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001968 return;
1969 }
1970
1971 am->addDefaultAssets();
1972
Steve Block71f2cf12011-10-20 11:56:00 +01001973 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001974 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975}
1976
1977static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1978{
1979 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001980 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001981 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001982 if (am != NULL) {
1983 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001984 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 }
1986}
1987
1988static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1989{
1990 return Asset::getGlobalCount();
1991}
1992
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001993static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1994{
1995 String8 alloc = Asset::getAssetAllocations();
1996 if (alloc.length() <= 0) {
1997 return NULL;
1998 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001999
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002000 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002001 return str;
2002}
2003
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2005{
2006 return AssetManager::getGlobalCount();
2007}
2008
2009// ----------------------------------------------------------------------------
2010
2011/*
2012 * JNI registration.
2013 */
2014static JNINativeMethod gAssetManagerMethods[] = {
2015 /* name, signature, funcPtr */
2016
2017 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002018 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 (void*) android_content_AssetManager_openAsset },
2020 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2021 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002022 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 (void*) android_content_AssetManager_openNonAssetNative },
2024 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2025 (void*) android_content_AssetManager_openNonAssetFdNative },
2026 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2027 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002028 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002030 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002032 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002034 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002036 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002038 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002040 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002042 { "addOverlayPath", "(Ljava/lang/String;)I",
2043 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 { "isUpToDate", "()Z",
2045 (void*) android_content_AssetManager_isUpToDate },
2046
2047 // Resources.
2048 { "setLocale", "(Ljava/lang/String;)V",
2049 (void*) android_content_AssetManager_setLocale },
2050 { "getLocales", "()[Ljava/lang/String;",
2051 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002052 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_setConfiguration },
2054 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2055 (void*) android_content_AssetManager_getResourceIdentifier },
2056 { "getResourceName","(I)Ljava/lang/String;",
2057 (void*) android_content_AssetManager_getResourceName },
2058 { "getResourcePackageName","(I)Ljava/lang/String;",
2059 (void*) android_content_AssetManager_getResourcePackageName },
2060 { "getResourceTypeName","(I)Ljava/lang/String;",
2061 (void*) android_content_AssetManager_getResourceTypeName },
2062 { "getResourceEntryName","(I)Ljava/lang/String;",
2063 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002064 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 (void*) android_content_AssetManager_loadResourceValue },
2066 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2067 (void*) android_content_AssetManager_loadResourceBagValue },
2068 { "getStringBlockCount","()I",
2069 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002070 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_getNativeStringBlock },
2072 { "getCookieName","(I)Ljava/lang/String;",
2073 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002074 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2075 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076
2077 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002078 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002080 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002082 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002084 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002086 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002088 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002090 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002092 { "resolveAttrs","(JII[I[I[I[I)Z",
2093 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002094 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 (void*) android_content_AssetManager_retrieveAttributes },
2096 { "getArraySize","(I)I",
2097 (void*) android_content_AssetManager_getArraySize },
2098 { "retrieveArray","(I[I)I",
2099 (void*) android_content_AssetManager_retrieveArray },
2100
2101 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002102 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 (void*) android_content_AssetManager_openXmlAssetNative },
2104
2105 // Arrays.
2106 { "getArrayStringResource","(I)[Ljava/lang/String;",
2107 (void*) android_content_AssetManager_getArrayStringResource },
2108 { "getArrayStringInfo","(I)[I",
2109 (void*) android_content_AssetManager_getArrayStringInfo },
2110 { "getArrayIntResource","(I)[I",
2111 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002112 { "getStyleAttributes","(I)[I",
2113 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114
2115 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002116 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 (void*) android_content_AssetManager_init },
2118 { "destroy", "()V",
2119 (void*) android_content_AssetManager_destroy },
2120 { "getGlobalAssetCount", "()I",
2121 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002122 { "getAssetAllocations", "()Ljava/lang/String;",
2123 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002125 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126};
2127
2128int register_android_content_AssetManager(JNIEnv* env)
2129{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002130 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2131 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2132 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2133 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2134 "Ljava/lang/CharSequence;");
2135 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2136 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2137 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2138 "changingConfigurations", "I");
2139 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140
Andreas Gampe987f79f2014-11-18 17:29:46 -08002141 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2142 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2143 "Landroid/os/ParcelFileDescriptor;");
2144 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2145 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146
Andreas Gampe987f79f2014-11-18 17:29:46 -08002147 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2148 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149
Andreas Gampe987f79f2014-11-18 17:29:46 -08002150 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2151 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152
Andreas Gampe987f79f2014-11-18 17:29:46 -08002153 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2154 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2155 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2156 "<init>", "()V");
2157 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2158 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002159
Andreas Gampe987f79f2014-11-18 17:29:46 -08002160 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2161 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162}
2163
2164}; // namespace android