blob: 0ff2524d8ec83a74041e6e132cf174890577630b [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
Dan Albert46d84442014-11-18 16:07:51 -080022#include <inttypes.h>
23#include <linux/capability.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010025#include <sys/types.h>
26#include <sys/wait.h>
27
Dan Albert46d84442014-11-18 16:07:51 -080028#include <private/android_filesystem_config.h> // for AID_SYSTEM
29
Dan Albert3a091b72014-11-20 15:41:25 -080030#include "androidfw/Asset.h"
31#include "androidfw/AssetManager.h"
32#include "androidfw/AttributeFinder.h"
33#include "androidfw/ResourceTypes.h"
34#include "android_runtime/AndroidRuntime.h"
35#include "android_util_Binder.h"
36#include "core_jni_helpers.h"
37#include "jni.h"
Dan Albert46d84442014-11-18 16:07:51 -080038#include "JNIHelp.h"
39#include "ScopedStringChars.h"
40#include "ScopedUtfChars.h"
Dan Albert46d84442014-11-18 16:07:51 -080041#include "utils/Log.h"
42#include "utils/misc.h"
43
Mårten Kongstad48d22322014-01-31 14:43:27 +010044extern "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
Adam Lesinski2738c962015-05-14 14:25:36 -0700618 // Constants duplicated from Java class android.content.res.Configuration.
619 static const jint kScreenLayoutRoundMask = 0x300;
620 static const jint kScreenLayoutRoundShift = 8;
621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800622 config.mcc = (uint16_t)mcc;
623 config.mnc = (uint16_t)mnc;
624 config.orientation = (uint8_t)orientation;
625 config.touchscreen = (uint8_t)touchscreen;
626 config.density = (uint16_t)density;
627 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700628 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 config.navigation = (uint8_t)navigation;
630 config.screenWidth = (uint16_t)screenWidth;
631 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700632 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700633 config.screenWidthDp = (uint16_t)screenWidthDp;
634 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700635 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100636 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 config.sdkVersion = (uint16_t)sdkVersion;
638 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700639
640 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
641 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
642 // into screenLayout2.
643 config.screenLayout2 =
644 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
649}
650
651static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
652 jstring name,
653 jstring defType,
654 jstring defPackage)
655{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700656 ScopedStringChars name16(env, name);
657 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 return 0;
659 }
660
661 AssetManager* am = assetManagerForJavaObject(env, clazz);
662 if (am == NULL) {
663 return 0;
664 }
665
Dan Albert66987492014-11-20 11:41:21 -0800666 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
667 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
668 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 jsize defTypeLen = defType
670 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800671 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
672 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
673 NULL))
674 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 jsize defPackageLen = defPackage
676 ? env->GetStringLength(defPackage) : 0;
677
678 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800679 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
680 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681
682 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800683 env->ReleaseStringChars(defPackage,
684 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 }
686 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800687 env->ReleaseStringChars(defType,
688 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
691 return ident;
692}
693
694static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
695 jint resid)
696{
697 AssetManager* am = assetManagerForJavaObject(env, clazz);
698 if (am == NULL) {
699 return NULL;
700 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700703 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 return NULL;
705 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 String16 str;
708 if (name.package != NULL) {
709 str.setTo(name.package, name.packageLen);
710 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700711 if (name.type8 != NULL || name.type != 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.type8 != NULL) {
717 str.append(String16(name.type8, name.typeLen));
718 } else {
719 str.append(name.type, name.typeLen);
720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700722 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 if (str.size() > 0) {
724 char16_t div = '/';
725 str.append(&div, 1);
726 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700727 if (name.name8 != NULL) {
728 str.append(String16(name.name8, name.nameLen));
729 } else {
730 str.append(name.name, name.nameLen);
731 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 return env->NewString((const jchar*)str.string(), str.size());
735}
736
737static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
738 jint resid)
739{
740 AssetManager* am = assetManagerForJavaObject(env, clazz);
741 if (am == NULL) {
742 return NULL;
743 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700746 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 return NULL;
748 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 if (name.package != NULL) {
751 return env->NewString((const jchar*)name.package, name.packageLen);
752 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 return NULL;
755}
756
757static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
758 jint resid)
759{
760 AssetManager* am = assetManagerForJavaObject(env, clazz);
761 if (am == NULL) {
762 return NULL;
763 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700766 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 return NULL;
768 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700769
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700770 if (name.type8 != NULL) {
771 return env->NewStringUTF(name.type8);
772 }
773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 if (name.type != NULL) {
775 return env->NewString((const jchar*)name.type, name.typeLen);
776 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 return NULL;
779}
780
781static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
782 jint resid)
783{
784 AssetManager* am = assetManagerForJavaObject(env, clazz);
785 if (am == NULL) {
786 return NULL;
787 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700790 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 return NULL;
792 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700793
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700794 if (name.name8 != NULL) {
795 return env->NewStringUTF(name.name8);
796 }
797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 if (name.name != NULL) {
799 return env->NewString((const jchar*)name.name, name.nameLen);
800 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 return NULL;
803}
804
805static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
806 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700807 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 jobject outValue,
809 jboolean resolve)
810{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800811 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800812 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700813 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 AssetManager* am = assetManagerForJavaObject(env, clazz);
816 if (am == NULL) {
817 return 0;
818 }
819 const ResTable& res(am->getResources());
820
821 Res_value value;
822 ResTable_config config;
823 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700824 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800825 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800826 if (block == BAD_INDEX) {
827 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
828 return 0;
829 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800830 }
831 uint32_t ref = ident;
832 if (resolve) {
833 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
834 if (kThrowOnBadId) {
835 if (block == BAD_INDEX) {
836 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
837 return 0;
838 }
839 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000841 if (block >= 0) {
842 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
843 }
844
845 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800846}
847
848static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
849 jint ident, jint bagEntryId,
850 jobject outValue, jboolean resolve)
851{
852 AssetManager* am = assetManagerForJavaObject(env, clazz);
853 if (am == NULL) {
854 return 0;
855 }
856 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 // Now lock down the resource object and start pulling stuff from it.
859 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 ssize_t block = -1;
862 Res_value value;
863
864 const ResTable::bag_entry* entry = NULL;
865 uint32_t typeSpecFlags;
866 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
867
868 for (ssize_t i=0; i<entryCount; i++) {
869 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
870 block = entry->stringBlock;
871 value = entry->map.value;
872 }
873 entry++;
874 }
875
876 res.unlock();
877
878 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000879 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 uint32_t ref = ident;
883 if (resolve) {
884 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800885 if (kThrowOnBadId) {
886 if (block == BAD_INDEX) {
887 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
888 return 0;
889 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800890 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000892 if (block >= 0) {
893 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
894 }
895
896 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897}
898
899static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
900{
901 AssetManager* am = assetManagerForJavaObject(env, clazz);
902 if (am == NULL) {
903 return 0;
904 }
905 return am->getResources().getTableCount();
906}
907
Ashok Bhat896043d2014-01-17 16:02:38 +0000908static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 jint block)
910{
911 AssetManager* am = assetManagerForJavaObject(env, clazz);
912 if (am == NULL) {
913 return 0;
914 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000915 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916}
917
918static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
919 jint cookie)
920{
921 AssetManager* am = assetManagerForJavaObject(env, clazz);
922 if (am == NULL) {
923 return NULL;
924 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000925 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700927 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800928 return NULL;
929 }
930 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 return str;
932}
933
Adam Lesinskide898ff2014-01-29 18:20:45 -0800934static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
935{
936 AssetManager* am = assetManagerForJavaObject(env, clazz);
937 if (am == NULL) {
938 return 0;
939 }
940
941 const ResTable& res = am->getResources();
942
943 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
944 gSparseArrayOffsets.constructor);
945 const size_t N = res.getBasePackageCount();
946 for (size_t i = 0; i < N; i++) {
947 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -0800948 env->CallVoidMethod(
949 sparseArray, gSparseArrayOffsets.put,
950 static_cast<jint>(res.getBasePackageId(i)),
951 env->NewString(reinterpret_cast<const jchar*>(name.string()),
952 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -0800953 }
954 return sparseArray;
955}
956
Ashok Bhat896043d2014-01-17 16:02:38 +0000957static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958{
959 AssetManager* am = assetManagerForJavaObject(env, clazz);
960 if (am == NULL) {
961 return 0;
962 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964}
965
966static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000967 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968{
Ashok Bhat896043d2014-01-17 16:02:38 +0000969 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 delete theme;
971}
972
973static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000974 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 jint styleRes,
976 jboolean force)
977{
Ashok Bhat896043d2014-01-17 16:02:38 +0000978 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 theme->applyStyle(styleRes, force ? true : false);
980}
981
982static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000983 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984{
Ashok Bhat896043d2014-01-17 16:02:38 +0000985 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
986 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 dest->setTo(*src);
988}
989
Alan Viverettee54d2452015-05-06 10:41:43 -0700990static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
991{
992 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
993 theme->clear();
994}
995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000997 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998{
Ashok Bhat896043d2014-01-17 16:02:38 +0000999 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 const ResTable& res(theme->getResTable());
1001
1002 Res_value value;
1003 // XXX value could be different in different configs!
1004 uint32_t typeSpecFlags = 0;
1005 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1006 uint32_t ref = 0;
1007 if (resolve) {
1008 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001009 if (kThrowOnBadId) {
1010 if (block == BAD_INDEX) {
1011 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1012 return 0;
1013 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 }
1016 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1017}
1018
Alan Viverettec1d52792015-05-05 09:49:03 -07001019static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1020 jlong themeHandle)
1021{
1022 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1023 return theme->getChangingConfigurations();
1024}
1025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001027 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 jstring tag, jstring prefix)
1029{
Ashok Bhat896043d2014-01-17 16:02:38 +00001030 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001032 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 // XXX Need to use params.
1035 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036}
1037
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001038class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1039public:
1040 XmlAttributeFinder(const ResXMLParser* parser)
1041 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1042 , mParser(parser) {}
1043
1044 inline uint32_t getAttribute(jsize index) const {
1045 return mParser->getAttributeNameResID(index);
1046 }
1047
1048private:
1049 const ResXMLParser* mParser;
1050};
1051
1052class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1053public:
1054 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1055 : BackTrackingAttributeFinder(start, end) {}
1056
1057 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1058 return entry->map.name.ident;
1059 }
1060};
1061
Alan Viverette52b999f2014-03-24 18:00:26 -07001062static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1063 jlong themeToken,
1064 jint defStyleAttr,
1065 jint defStyleRes,
1066 jintArray inValues,
1067 jintArray attrs,
1068 jintArray outValues,
1069 jintArray outIndices)
1070{
1071 if (themeToken == 0) {
1072 jniThrowNullPointerException(env, "theme token");
1073 return JNI_FALSE;
1074 }
1075 if (attrs == NULL) {
1076 jniThrowNullPointerException(env, "attrs");
1077 return JNI_FALSE;
1078 }
1079 if (outValues == NULL) {
1080 jniThrowNullPointerException(env, "out values");
1081 return JNI_FALSE;
1082 }
1083
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001084 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001085 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1086 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001087 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001088
1089 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1090 const ResTable& res = theme->getResTable();
1091 ResTable_config config;
1092 Res_value value;
1093
1094 const jsize NI = env->GetArrayLength(attrs);
1095 const jsize NV = env->GetArrayLength(outValues);
1096 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1097 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1098 return JNI_FALSE;
1099 }
1100
1101 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1102 if (src == NULL) {
1103 return JNI_FALSE;
1104 }
1105
1106 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1107 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1108
1109 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1110 jint* dest = baseDest;
1111 if (dest == NULL) {
1112 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1113 return JNI_FALSE;
1114 }
1115
1116 jint* indices = NULL;
1117 int indicesIdx = 0;
1118 if (outIndices != NULL) {
1119 if (env->GetArrayLength(outIndices) > NI) {
1120 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1121 }
1122 }
1123
1124 // Load default style from attribute, if specified...
1125 uint32_t defStyleBagTypeSetFlags = 0;
1126 if (defStyleAttr != 0) {
1127 Res_value value;
1128 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1129 if (value.dataType == Res_value::TYPE_REFERENCE) {
1130 defStyleRes = value.data;
1131 }
1132 }
1133 }
1134
1135 // Now lock down the resource object and start pulling stuff from it.
1136 res.lock();
1137
1138 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001139 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001140 uint32_t defStyleTypeSetFlags = 0;
1141 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001142 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001143 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001144 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1145 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001146
1147 // Now iterate through all of the attributes that the client has requested,
1148 // filling in each with whatever data we can find.
1149 ssize_t block = 0;
1150 uint32_t typeSetFlags;
1151 for (jsize ii=0; ii<NI; ii++) {
1152 const uint32_t curIdent = (uint32_t)src[ii];
1153
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001154 if (kDebugStyles) {
1155 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1156 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001157
1158 // Try to find a value for this attribute... we prioritize values
1159 // coming from, first XML attributes, then XML style, then default
1160 // style, and finally the theme.
1161 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001162 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 typeSetFlags = 0;
1164 config.density = 0;
1165
1166 // Retrieve the current input value if available.
1167 if (NSV > 0 && srcValues[ii] != 0) {
1168 block = -1;
1169 value.dataType = Res_value::TYPE_ATTRIBUTE;
1170 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001171 if (kDebugStyles) {
1172 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1173 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001174 }
1175
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001176 if (value.dataType == Res_value::TYPE_NULL) {
1177 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1178 if (defStyleEntry != defStyleEnd) {
1179 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001180 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001181 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001182 if (kDebugStyles) {
1183 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1184 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001185 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001186 }
1187
1188 uint32_t resid = 0;
1189 if (value.dataType != Res_value::TYPE_NULL) {
1190 // Take care of resolving the found resource to its final value.
1191 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1192 &resid, &typeSetFlags, &config);
1193 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001194 if (kDebugStyles) {
1195 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1196 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001197 } else {
1198 // If we still don't have a value for this attribute, try to find
1199 // it in the theme!
1200 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1201 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001202 if (kDebugStyles) {
1203 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1204 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001205 newBlock = res.resolveReference(&value, block, &resid,
1206 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001207 if (kThrowOnBadId) {
1208 if (newBlock == BAD_INDEX) {
1209 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1210 return JNI_FALSE;
1211 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001212 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001213 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001214 if (kDebugStyles) {
1215 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1216 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001217 }
1218 }
1219
1220 // Deal with the special @null value -- it turns back to TYPE_NULL.
1221 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001222 if (kDebugStyles) {
1223 ALOGI("-> Setting to @null!");
1224 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001225 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001226 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001227 block = -1;
1228 }
1229
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001230 if (kDebugStyles) {
1231 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1232 value.data);
1233 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001234
1235 // Write the final value back to Java.
1236 dest[STYLE_TYPE] = value.dataType;
1237 dest[STYLE_DATA] = value.data;
1238 dest[STYLE_ASSET_COOKIE] =
1239 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1240 dest[STYLE_RESOURCE_ID] = resid;
1241 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1242 dest[STYLE_DENSITY] = config.density;
1243
1244 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1245 indicesIdx++;
1246 indices[indicesIdx] = ii;
1247 }
1248
1249 dest += STYLE_NUM_ENTRIES;
1250 }
1251
1252 res.unlock();
1253
1254 if (indices != NULL) {
1255 indices[0] = indicesIdx;
1256 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1257 }
1258 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1259 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1260 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1261
1262 return JNI_TRUE;
1263}
1264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001266 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 jint defStyleAttr,
1268 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001269 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 jintArray attrs,
1271 jintArray outValues,
1272 jintArray outIndices)
1273{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001274 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001275 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001276 return JNI_FALSE;
1277 }
1278 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001279 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001280 return JNI_FALSE;
1281 }
1282 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001283 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 return JNI_FALSE;
1285 }
1286
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001287 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001288 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1289 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1290 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001291 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001292
Ashok Bhat896043d2014-01-17 16:02:38 +00001293 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001295 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001296 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 Res_value value;
1298
1299 const jsize NI = env->GetArrayLength(attrs);
1300 const jsize NV = env->GetArrayLength(outValues);
1301 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001302 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 return JNI_FALSE;
1304 }
1305
1306 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1307 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 return JNI_FALSE;
1309 }
1310
1311 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1312 jint* dest = baseDest;
1313 if (dest == NULL) {
1314 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 return JNI_FALSE;
1316 }
1317
1318 jint* indices = NULL;
1319 int indicesIdx = 0;
1320 if (outIndices != NULL) {
1321 if (env->GetArrayLength(outIndices) > NI) {
1322 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1323 }
1324 }
1325
1326 // Load default style from attribute, if specified...
1327 uint32_t defStyleBagTypeSetFlags = 0;
1328 if (defStyleAttr != 0) {
1329 Res_value value;
1330 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1331 if (value.dataType == Res_value::TYPE_REFERENCE) {
1332 defStyleRes = value.data;
1333 }
1334 }
1335 }
1336
1337 // Retrieve the style class associated with the current XML tag.
1338 int style = 0;
1339 uint32_t styleBagTypeSetFlags = 0;
1340 if (xmlParser != NULL) {
1341 ssize_t idx = xmlParser->indexOfStyle();
1342 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1343 if (value.dataType == value.TYPE_ATTRIBUTE) {
1344 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1345 value.dataType = Res_value::TYPE_NULL;
1346 }
1347 }
1348 if (value.dataType == value.TYPE_REFERENCE) {
1349 style = value.data;
1350 }
1351 }
1352 }
1353
1354 // Now lock down the resource object and start pulling stuff from it.
1355 res.lock();
1356
1357 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001358 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 uint32_t defStyleTypeSetFlags = 0;
1360 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001361 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001363 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1364 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365
1366 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001367 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001369 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001371 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1372 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373
1374 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001376 XmlAttributeFinder xmlAttrFinder(xmlParser);
1377 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378
1379 // Now iterate through all of the attributes that the client has requested,
1380 // filling in each with whatever data we can find.
1381 ssize_t block = 0;
1382 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001383 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 const uint32_t curIdent = (uint32_t)src[ii];
1385
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001386 if (kDebugStyles) {
1387 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1388 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 // Try to find a value for this attribute... we prioritize values
1391 // coming from, first XML attributes, then XML style, then default
1392 // style, and finally the theme.
1393 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001394 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001396 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001398 // Walk through the xml attributes looking for the requested attribute.
1399 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1400 if (xmlAttrIdx != xmlAttrEnd) {
1401 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001403 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001404 if (kDebugStyles) {
1405 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
1408
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001409 if (value.dataType == Res_value::TYPE_NULL) {
1410 // Walk through the style class values looking for the requested attribute.
1411 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1412 if (styleAttrEntry != styleAttrEnd) {
1413 // We found the attribute we were looking for.
1414 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001416 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001417 if (kDebugStyles) {
1418 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 }
1422
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001423 if (value.dataType == Res_value::TYPE_NULL) {
1424 // Walk through the default style values looking for the requested attribute.
1425 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1426 if (defStyleAttrEntry != defStyleAttrEnd) {
1427 // We found the attribute we were looking for.
1428 block = defStyleAttrEntry->stringBlock;
1429 typeSetFlags = styleTypeSetFlags;
1430 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001431 if (kDebugStyles) {
1432 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 }
1436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 uint32_t resid = 0;
1438 if (value.dataType != Res_value::TYPE_NULL) {
1439 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001440 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1441 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001442 if (newBlock >= 0) {
1443 block = newBlock;
1444 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001445
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001446 if (kDebugStyles) {
1447 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 } else {
1450 // If we still don't have a value for this attribute, try to find
1451 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1453 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001454 if (kDebugStyles) {
1455 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1456 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001457 newBlock = res.resolveReference(&value, block, &resid,
1458 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001459 if (kThrowOnBadId) {
1460 if (newBlock == BAD_INDEX) {
1461 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1462 return JNI_FALSE;
1463 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001464 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001465
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001466 if (newBlock >= 0) {
1467 block = newBlock;
1468 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001469
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001470 if (kDebugStyles) {
1471 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 }
1474 }
1475
1476 // Deal with the special @null value -- it turns back to TYPE_NULL.
1477 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001478 if (kDebugStyles) {
1479 ALOGI("-> Setting to @null!");
1480 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001482 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001483 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 }
1485
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001486 if (kDebugStyles) {
1487 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489
1490 // Write the final value back to Java.
1491 dest[STYLE_TYPE] = value.dataType;
1492 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001493 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1494 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 dest[STYLE_RESOURCE_ID] = resid;
1496 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001497 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1500 indicesIdx++;
1501 indices[indicesIdx] = ii;
1502 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 dest += STYLE_NUM_ENTRIES;
1505 }
1506
1507 res.unlock();
1508
1509 if (indices != NULL) {
1510 indices[0] = indicesIdx;
1511 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1512 }
1513 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1514 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1515
1516 return JNI_TRUE;
1517}
1518
1519static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001520 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 jintArray attrs,
1522 jintArray outValues,
1523 jintArray outIndices)
1524{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001525 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001526 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001527 return JNI_FALSE;
1528 }
1529 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001530 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001531 return JNI_FALSE;
1532 }
1533 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001534 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 return JNI_FALSE;
1536 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 AssetManager* am = assetManagerForJavaObject(env, clazz);
1539 if (am == NULL) {
1540 return JNI_FALSE;
1541 }
1542 const ResTable& res(am->getResources());
1543 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001544 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 const jsize NI = env->GetArrayLength(attrs);
1548 const jsize NV = env->GetArrayLength(outValues);
1549 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001550 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 return JNI_FALSE;
1552 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1555 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 return JNI_FALSE;
1557 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1560 jint* dest = baseDest;
1561 if (dest == NULL) {
1562 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 return JNI_FALSE;
1564 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 jint* indices = NULL;
1567 int indicesIdx = 0;
1568 if (outIndices != NULL) {
1569 if (env->GetArrayLength(outIndices) > NI) {
1570 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1571 }
1572 }
1573
1574 // Now lock down the resource object and start pulling stuff from it.
1575 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 // Retrieve the XML attributes, if requested.
1578 const jsize NX = xmlParser->getAttributeCount();
1579 jsize ix=0;
1580 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 // Now iterate through all of the attributes that the client has requested,
1585 // filling in each with whatever data we can find.
1586 ssize_t block = 0;
1587 uint32_t typeSetFlags;
1588 for (jsize ii=0; ii<NI; ii++) {
1589 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 // Try to find a value for this attribute...
1592 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001593 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001595 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001598 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 ix++;
1600 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1601 }
1602 // Retrieve the current XML attribute if it matches, and step to next.
1603 if (ix < NX && curIdent == curXmlAttr) {
1604 block = kXmlBlock;
1605 xmlParser->getAttributeValue(ix, &value);
1606 ix++;
1607 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1608 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1611 uint32_t resid = 0;
1612 if (value.dataType != Res_value::TYPE_NULL) {
1613 // Take care of resolving the found resource to its final value.
1614 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001615 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1616 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001617 if (kThrowOnBadId) {
1618 if (newBlock == BAD_INDEX) {
1619 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1620 return JNI_FALSE;
1621 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001622 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 if (newBlock >= 0) block = newBlock;
1624 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 // Deal with the special @null value -- it turns back to TYPE_NULL.
1627 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1628 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001629 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 // Write the final value back to Java.
1635 dest[STYLE_TYPE] = value.dataType;
1636 dest[STYLE_DATA] = value.data;
1637 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001638 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 dest[STYLE_RESOURCE_ID] = resid;
1640 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001641 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1644 indicesIdx++;
1645 indices[indicesIdx] = ii;
1646 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 dest += STYLE_NUM_ENTRIES;
1649 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 if (indices != NULL) {
1654 indices[0] = indicesIdx;
1655 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1656 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1659 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 return JNI_TRUE;
1662}
1663
1664static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1665 jint id)
1666{
1667 AssetManager* am = assetManagerForJavaObject(env, clazz);
1668 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001669 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 }
1671 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 res.lock();
1674 const ResTable::bag_entry* defStyleEnt = NULL;
1675 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1676 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001677
Ashok Bhat896043d2014-01-17 16:02:38 +00001678 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679}
1680
1681static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1682 jint id,
1683 jintArray outValues)
1684{
1685 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001686 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 return JNI_FALSE;
1688 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 AssetManager* am = assetManagerForJavaObject(env, clazz);
1691 if (am == NULL) {
1692 return JNI_FALSE;
1693 }
1694 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001695 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 Res_value value;
1697 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1702 jint* dest = baseDest;
1703 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001704 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 return JNI_FALSE;
1706 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 // Now lock down the resource object and start pulling stuff from it.
1709 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 const ResTable::bag_entry* arrayEnt = NULL;
1712 uint32_t arrayTypeSetFlags = 0;
1713 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1714 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1715 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 int i = 0;
1718 uint32_t typeSetFlags;
1719 while (i < NV && arrayEnt < endArrayEnt) {
1720 block = arrayEnt->stringBlock;
1721 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001722 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 uint32_t resid = 0;
1726 if (value.dataType != Res_value::TYPE_NULL) {
1727 // Take care of resolving the found resource to its final value.
1728 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001729 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1730 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001731 if (kThrowOnBadId) {
1732 if (newBlock == BAD_INDEX) {
1733 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1734 return JNI_FALSE;
1735 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001736 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 if (newBlock >= 0) block = newBlock;
1738 }
1739
1740 // Deal with the special @null value -- it turns back to TYPE_NULL.
1741 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1742 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001743 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 }
1745
1746 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1747
1748 // Write the final value back to Java.
1749 dest[STYLE_TYPE] = value.dataType;
1750 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001751 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 dest[STYLE_RESOURCE_ID] = resid;
1753 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001754 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 dest += STYLE_NUM_ENTRIES;
1756 i+= STYLE_NUM_ENTRIES;
1757 arrayEnt++;
1758 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 return i;
1767}
1768
Ashok Bhat896043d2014-01-17 16:02:38 +00001769static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 jint cookie,
1771 jstring fileName)
1772{
1773 AssetManager* am = assetManagerForJavaObject(env, clazz);
1774 if (am == NULL) {
1775 return 0;
1776 }
1777
Steve Block71f2cf12011-10-20 11:56:00 +01001778 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779
Elliott Hughes69a017b2011-04-08 14:10:28 -07001780 ScopedUtfChars fileName8(env, fileName);
1781 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 return 0;
1783 }
1784
Adam Lesinskide898ff2014-01-29 18:20:45 -08001785 int32_t assetCookie = static_cast<int32_t>(cookie);
1786 Asset* a = assetCookie
1787 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1788 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789
1790 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001791 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 return 0;
1793 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794
Adam Lesinskide898ff2014-01-29 18:20:45 -08001795 const DynamicRefTable* dynamicRefTable =
1796 am->getResources().getDynamicRefTableForCookie(assetCookie);
1797 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1799 a->close();
1800 delete a;
1801
1802 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001803 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 return 0;
1805 }
1806
Ashok Bhat896043d2014-01-17 16:02:38 +00001807 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808}
1809
1810static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1811 jint arrayResId)
1812{
1813 AssetManager* am = assetManagerForJavaObject(env, clazz);
1814 if (am == NULL) {
1815 return NULL;
1816 }
1817 const ResTable& res(am->getResources());
1818
1819 const ResTable::bag_entry* startOfBag;
1820 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1821 if (N < 0) {
1822 return NULL;
1823 }
1824
1825 jintArray array = env->NewIntArray(N * 2);
1826 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 res.unlockBag(startOfBag);
1828 return NULL;
1829 }
1830
1831 Res_value value;
1832 const ResTable::bag_entry* bag = startOfBag;
1833 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1834 jint stringIndex = -1;
1835 jint stringBlock = 0;
1836 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 // Take care of resolving the found resource to its final value.
1839 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1840 if (value.dataType == Res_value::TYPE_STRING) {
1841 stringIndex = value.data;
1842 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001843
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001844 if (kThrowOnBadId) {
1845 if (stringBlock == BAD_INDEX) {
1846 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1847 return array;
1848 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001849 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 //todo: It might be faster to allocate a C array to contain
1852 // the blocknums and indices, put them in there and then
1853 // do just one SetIntArrayRegion()
1854 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1855 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1856 j = j + 2;
1857 }
1858 res.unlockBag(startOfBag);
1859 return array;
1860}
1861
1862static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1863 jint arrayResId)
1864{
1865 AssetManager* am = assetManagerForJavaObject(env, clazz);
1866 if (am == NULL) {
1867 return NULL;
1868 }
1869 const ResTable& res(am->getResources());
1870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 const ResTable::bag_entry* startOfBag;
1872 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1873 if (N < 0) {
1874 return NULL;
1875 }
1876
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001877 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001878 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 res.unlockBag(startOfBag);
1880 return NULL;
1881 }
1882
1883 Res_value value;
1884 const ResTable::bag_entry* bag = startOfBag;
1885 size_t strLen = 0;
1886 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1887 value = bag->map.value;
1888 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 // Take care of resolving the found resource to its final value.
1891 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001892 if (kThrowOnBadId) {
1893 if (block == BAD_INDEX) {
1894 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1895 return array;
1896 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001897 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001898 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001899 const ResStringPool* pool = res.getTableStringBlock(block);
1900 const char* str8 = pool->string8At(value.data, &strLen);
1901 if (str8 != NULL) {
1902 str = env->NewStringUTF(str8);
1903 } else {
1904 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001905 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1906 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001907 }
1908
1909 // If one of our NewString{UTF} calls failed due to memory, an
1910 // exception will be pending.
1911 if (env->ExceptionCheck()) {
1912 res.unlockBag(startOfBag);
1913 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 }
Kenny Root780d2a12010-02-22 22:36:26 -08001915
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001916 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001917
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001918 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1919 // If we have a large amount of strings in our array, we might
1920 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001921 env->DeleteLocalRef(str);
1922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 }
1924 res.unlockBag(startOfBag);
1925 return array;
1926}
1927
1928static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1929 jint arrayResId)
1930{
1931 AssetManager* am = assetManagerForJavaObject(env, clazz);
1932 if (am == NULL) {
1933 return NULL;
1934 }
1935 const ResTable& res(am->getResources());
1936
1937 const ResTable::bag_entry* startOfBag;
1938 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1939 if (N < 0) {
1940 return NULL;
1941 }
1942
1943 jintArray array = env->NewIntArray(N);
1944 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 res.unlockBag(startOfBag);
1946 return NULL;
1947 }
1948
1949 Res_value value;
1950 const ResTable::bag_entry* bag = startOfBag;
1951 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1952 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 // Take care of resolving the found resource to its final value.
1955 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001956 if (kThrowOnBadId) {
1957 if (block == BAD_INDEX) {
1958 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1959 return array;
1960 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 if (value.dataType >= Res_value::TYPE_FIRST_INT
1963 && value.dataType <= Res_value::TYPE_LAST_INT) {
1964 int intVal = value.data;
1965 env->SetIntArrayRegion(array, i, 1, &intVal);
1966 }
1967 }
1968 res.unlockBag(startOfBag);
1969 return array;
1970}
1971
Jon Miranda042ad632014-09-03 17:57:35 -07001972static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1973 jint styleId)
1974{
1975 AssetManager* am = assetManagerForJavaObject(env, clazz);
1976 if (am == NULL) {
1977 return NULL;
1978 }
1979 const ResTable& res(am->getResources());
1980
1981 const ResTable::bag_entry* startOfBag;
1982 const ssize_t N = res.lockBag(styleId, &startOfBag);
1983 if (N < 0) {
1984 return NULL;
1985 }
1986
1987 jintArray array = env->NewIntArray(N);
1988 if (array == NULL) {
1989 res.unlockBag(startOfBag);
1990 return NULL;
1991 }
1992
Jon Miranda042ad632014-09-03 17:57:35 -07001993 const ResTable::bag_entry* bag = startOfBag;
1994 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1995 int resourceId = bag->map.name.ident;
1996 env->SetIntArrayRegion(array, i, 1, &resourceId);
1997 }
1998 res.unlockBag(startOfBag);
1999 return array;
2000}
2001
Mårten Kongstad48d22322014-01-31 14:43:27 +01002002static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002004 if (isSystem) {
2005 verifySystemIdmaps();
2006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 AssetManager* am = new AssetManager();
2008 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002009 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 return;
2011 }
2012
2013 am->addDefaultAssets();
2014
Steve Block71f2cf12011-10-20 11:56:00 +01002015 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002016 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017}
2018
2019static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2020{
2021 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002022 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002023 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 if (am != NULL) {
2025 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002026 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 }
2028}
2029
2030static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2031{
2032 return Asset::getGlobalCount();
2033}
2034
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002035static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2036{
2037 String8 alloc = Asset::getAssetAllocations();
2038 if (alloc.length() <= 0) {
2039 return NULL;
2040 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002041
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002042 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002043 return str;
2044}
2045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2047{
2048 return AssetManager::getGlobalCount();
2049}
2050
2051// ----------------------------------------------------------------------------
2052
2053/*
2054 * JNI registration.
2055 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002056static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 /* name, signature, funcPtr */
2058
2059 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002060 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 (void*) android_content_AssetManager_openAsset },
2062 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2063 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002064 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 (void*) android_content_AssetManager_openNonAssetNative },
2066 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2067 (void*) android_content_AssetManager_openNonAssetFdNative },
2068 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2069 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002070 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002072 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002074 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002076 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002078 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002080 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002082 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002084 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002085 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 { "isUpToDate", "()Z",
2087 (void*) android_content_AssetManager_isUpToDate },
2088
2089 // Resources.
2090 { "setLocale", "(Ljava/lang/String;)V",
2091 (void*) android_content_AssetManager_setLocale },
2092 { "getLocales", "()[Ljava/lang/String;",
2093 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002094 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 (void*) android_content_AssetManager_setConfiguration },
2096 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2097 (void*) android_content_AssetManager_getResourceIdentifier },
2098 { "getResourceName","(I)Ljava/lang/String;",
2099 (void*) android_content_AssetManager_getResourceName },
2100 { "getResourcePackageName","(I)Ljava/lang/String;",
2101 (void*) android_content_AssetManager_getResourcePackageName },
2102 { "getResourceTypeName","(I)Ljava/lang/String;",
2103 (void*) android_content_AssetManager_getResourceTypeName },
2104 { "getResourceEntryName","(I)Ljava/lang/String;",
2105 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002106 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 (void*) android_content_AssetManager_loadResourceValue },
2108 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2109 (void*) android_content_AssetManager_loadResourceBagValue },
2110 { "getStringBlockCount","()I",
2111 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002112 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 (void*) android_content_AssetManager_getNativeStringBlock },
2114 { "getCookieName","(I)Ljava/lang/String;",
2115 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002116 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2117 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118
2119 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002120 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002122 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002124 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002126 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002128 { "clearTheme", "(J)V",
2129 (void*) android_content_AssetManager_clearTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002130 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 (void*) android_content_AssetManager_loadThemeAttributeValue },
Alan Viverettec1d52792015-05-05 09:49:03 -07002132 { "getThemeChangingConfigurations", "(J)I",
2133 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002134 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002136 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002137 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002138 { "resolveAttrs","(JII[I[I[I[I)Z",
2139 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002140 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141 (void*) android_content_AssetManager_retrieveAttributes },
2142 { "getArraySize","(I)I",
2143 (void*) android_content_AssetManager_getArraySize },
2144 { "retrieveArray","(I[I)I",
2145 (void*) android_content_AssetManager_retrieveArray },
2146
2147 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002148 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 (void*) android_content_AssetManager_openXmlAssetNative },
2150
2151 // Arrays.
2152 { "getArrayStringResource","(I)[Ljava/lang/String;",
2153 (void*) android_content_AssetManager_getArrayStringResource },
2154 { "getArrayStringInfo","(I)[I",
2155 (void*) android_content_AssetManager_getArrayStringInfo },
2156 { "getArrayIntResource","(I)[I",
2157 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002158 { "getStyleAttributes","(I)[I",
2159 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160
2161 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002162 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 (void*) android_content_AssetManager_init },
2164 { "destroy", "()V",
2165 (void*) android_content_AssetManager_destroy },
2166 { "getGlobalAssetCount", "()I",
2167 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002168 { "getAssetAllocations", "()Ljava/lang/String;",
2169 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002171 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172};
2173
2174int register_android_content_AssetManager(JNIEnv* env)
2175{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002176 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2177 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2178 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2179 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2180 "Ljava/lang/CharSequence;");
2181 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2182 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2183 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2184 "changingConfigurations", "I");
2185 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186
Andreas Gampe987f79f2014-11-18 17:29:46 -08002187 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2188 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2189 "Landroid/os/ParcelFileDescriptor;");
2190 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2191 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192
Andreas Gampe987f79f2014-11-18 17:29:46 -08002193 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2194 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195
Andreas Gampe987f79f2014-11-18 17:29:46 -08002196 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2197 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198
Andreas Gampe987f79f2014-11-18 17:29:46 -08002199 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2200 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2201 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2202 "<init>", "()V");
2203 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2204 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002205
Andreas Gampe987f79f2014-11-18 17:29:46 -08002206 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2207 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208}
2209
2210}; // namespace android