blob: db495dd4709fc4615de52bd0031f61c1cbbcfff9 [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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 config.mcc = (uint16_t)mcc;
619 config.mnc = (uint16_t)mnc;
620 config.orientation = (uint8_t)orientation;
621 config.touchscreen = (uint8_t)touchscreen;
622 config.density = (uint16_t)density;
623 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700624 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 config.navigation = (uint8_t)navigation;
626 config.screenWidth = (uint16_t)screenWidth;
627 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700628 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700629 config.screenWidthDp = (uint16_t)screenWidthDp;
630 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700631 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100632 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 config.sdkVersion = (uint16_t)sdkVersion;
634 config.minorVersion = 0;
635 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
638}
639
640static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
641 jstring name,
642 jstring defType,
643 jstring defPackage)
644{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700645 ScopedStringChars name16(env, name);
646 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 return 0;
648 }
649
650 AssetManager* am = assetManagerForJavaObject(env, clazz);
651 if (am == NULL) {
652 return 0;
653 }
654
Dan Albert66987492014-11-20 11:41:21 -0800655 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
656 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
657 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 jsize defTypeLen = defType
659 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800660 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
661 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
662 NULL))
663 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 jsize defPackageLen = defPackage
665 ? env->GetStringLength(defPackage) : 0;
666
667 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800668 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
669 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800672 env->ReleaseStringChars(defPackage,
673 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 }
675 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800676 env->ReleaseStringChars(defType,
677 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679
680 return ident;
681}
682
683static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
684 jint resid)
685{
686 AssetManager* am = assetManagerForJavaObject(env, clazz);
687 if (am == NULL) {
688 return NULL;
689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700692 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 return NULL;
694 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 String16 str;
697 if (name.package != NULL) {
698 str.setTo(name.package, name.packageLen);
699 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700700 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 if (str.size() > 0) {
702 char16_t div = ':';
703 str.append(&div, 1);
704 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700705 if (name.type8 != NULL) {
706 str.append(String16(name.type8, name.typeLen));
707 } else {
708 str.append(name.type, name.typeLen);
709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700711 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 if (str.size() > 0) {
713 char16_t div = '/';
714 str.append(&div, 1);
715 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700716 if (name.name8 != NULL) {
717 str.append(String16(name.name8, name.nameLen));
718 } else {
719 str.append(name.name, name.nameLen);
720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 return env->NewString((const jchar*)str.string(), str.size());
724}
725
726static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
727 jint resid)
728{
729 AssetManager* am = assetManagerForJavaObject(env, clazz);
730 if (am == NULL) {
731 return NULL;
732 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700735 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 return NULL;
737 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 if (name.package != NULL) {
740 return env->NewString((const jchar*)name.package, name.packageLen);
741 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 return NULL;
744}
745
746static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
747 jint resid)
748{
749 AssetManager* am = assetManagerForJavaObject(env, clazz);
750 if (am == NULL) {
751 return NULL;
752 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700755 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 return NULL;
757 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700758
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700759 if (name.type8 != NULL) {
760 return env->NewStringUTF(name.type8);
761 }
762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 if (name.type != NULL) {
764 return env->NewString((const jchar*)name.type, name.typeLen);
765 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 return NULL;
768}
769
770static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
771 jint resid)
772{
773 AssetManager* am = assetManagerForJavaObject(env, clazz);
774 if (am == NULL) {
775 return NULL;
776 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700779 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 return NULL;
781 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700782
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700783 if (name.name8 != NULL) {
784 return env->NewStringUTF(name.name8);
785 }
786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 if (name.name != NULL) {
788 return env->NewString((const jchar*)name.name, name.nameLen);
789 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 return NULL;
792}
793
794static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
795 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700796 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 jobject outValue,
798 jboolean resolve)
799{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800800 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800801 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700802 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 AssetManager* am = assetManagerForJavaObject(env, clazz);
805 if (am == NULL) {
806 return 0;
807 }
808 const ResTable& res(am->getResources());
809
810 Res_value value;
811 ResTable_config config;
812 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700813 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800814 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800815 if (block == BAD_INDEX) {
816 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
817 return 0;
818 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800819 }
820 uint32_t ref = ident;
821 if (resolve) {
822 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
823 if (kThrowOnBadId) {
824 if (block == BAD_INDEX) {
825 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
826 return 0;
827 }
828 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000830 if (block >= 0) {
831 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
832 }
833
834 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835}
836
837static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
838 jint ident, jint bagEntryId,
839 jobject outValue, jboolean resolve)
840{
841 AssetManager* am = assetManagerForJavaObject(env, clazz);
842 if (am == NULL) {
843 return 0;
844 }
845 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800847 // Now lock down the resource object and start pulling stuff from it.
848 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 ssize_t block = -1;
851 Res_value value;
852
853 const ResTable::bag_entry* entry = NULL;
854 uint32_t typeSpecFlags;
855 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
856
857 for (ssize_t i=0; i<entryCount; i++) {
858 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
859 block = entry->stringBlock;
860 value = entry->map.value;
861 }
862 entry++;
863 }
864
865 res.unlock();
866
867 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000868 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871 uint32_t ref = ident;
872 if (resolve) {
873 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800874 if (kThrowOnBadId) {
875 if (block == BAD_INDEX) {
876 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
877 return 0;
878 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000881 if (block >= 0) {
882 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
883 }
884
885 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800886}
887
888static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
889{
890 AssetManager* am = assetManagerForJavaObject(env, clazz);
891 if (am == NULL) {
892 return 0;
893 }
894 return am->getResources().getTableCount();
895}
896
Ashok Bhat896043d2014-01-17 16:02:38 +0000897static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898 jint block)
899{
900 AssetManager* am = assetManagerForJavaObject(env, clazz);
901 if (am == NULL) {
902 return 0;
903 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000904 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905}
906
907static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
908 jint cookie)
909{
910 AssetManager* am = assetManagerForJavaObject(env, clazz);
911 if (am == NULL) {
912 return NULL;
913 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000914 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700916 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 return NULL;
918 }
919 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 return str;
921}
922
Adam Lesinskide898ff2014-01-29 18:20:45 -0800923static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
924{
925 AssetManager* am = assetManagerForJavaObject(env, clazz);
926 if (am == NULL) {
927 return 0;
928 }
929
930 const ResTable& res = am->getResources();
931
932 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
933 gSparseArrayOffsets.constructor);
934 const size_t N = res.getBasePackageCount();
935 for (size_t i = 0; i < N; i++) {
936 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -0800937 env->CallVoidMethod(
938 sparseArray, gSparseArrayOffsets.put,
939 static_cast<jint>(res.getBasePackageId(i)),
940 env->NewString(reinterpret_cast<const jchar*>(name.string()),
941 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -0800942 }
943 return sparseArray;
944}
945
Ashok Bhat896043d2014-01-17 16:02:38 +0000946static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
948 AssetManager* am = assetManagerForJavaObject(env, clazz);
949 if (am == NULL) {
950 return 0;
951 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000952 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953}
954
955static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000956 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957{
Ashok Bhat896043d2014-01-17 16:02:38 +0000958 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 delete theme;
960}
961
962static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 jint styleRes,
965 jboolean force)
966{
Ashok Bhat896043d2014-01-17 16:02:38 +0000967 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 theme->applyStyle(styleRes, force ? true : false);
969}
970
971static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000972 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973{
Ashok Bhat896043d2014-01-17 16:02:38 +0000974 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
975 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 dest->setTo(*src);
977}
978
979static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000980 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981{
Ashok Bhat896043d2014-01-17 16:02:38 +0000982 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 const ResTable& res(theme->getResTable());
984
985 Res_value value;
986 // XXX value could be different in different configs!
987 uint32_t typeSpecFlags = 0;
988 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
989 uint32_t ref = 0;
990 if (resolve) {
991 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800992 if (kThrowOnBadId) {
993 if (block == BAD_INDEX) {
994 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
995 return 0;
996 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 }
999 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1000}
1001
Alan Viverettec1d52792015-05-05 09:49:03 -07001002static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1003 jlong themeHandle)
1004{
1005 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1006 return theme->getChangingConfigurations();
1007}
1008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001010 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 jstring tag, jstring prefix)
1012{
Ashok Bhat896043d2014-01-17 16:02:38 +00001013 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001015 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 // XXX Need to use params.
1018 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019}
1020
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001021class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1022public:
1023 XmlAttributeFinder(const ResXMLParser* parser)
1024 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1025 , mParser(parser) {}
1026
1027 inline uint32_t getAttribute(jsize index) const {
1028 return mParser->getAttributeNameResID(index);
1029 }
1030
1031private:
1032 const ResXMLParser* mParser;
1033};
1034
1035class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1036public:
1037 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1038 : BackTrackingAttributeFinder(start, end) {}
1039
1040 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1041 return entry->map.name.ident;
1042 }
1043};
1044
Alan Viverette52b999f2014-03-24 18:00:26 -07001045static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1046 jlong themeToken,
1047 jint defStyleAttr,
1048 jint defStyleRes,
1049 jintArray inValues,
1050 jintArray attrs,
1051 jintArray outValues,
1052 jintArray outIndices)
1053{
1054 if (themeToken == 0) {
1055 jniThrowNullPointerException(env, "theme token");
1056 return JNI_FALSE;
1057 }
1058 if (attrs == NULL) {
1059 jniThrowNullPointerException(env, "attrs");
1060 return JNI_FALSE;
1061 }
1062 if (outValues == NULL) {
1063 jniThrowNullPointerException(env, "out values");
1064 return JNI_FALSE;
1065 }
1066
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001067 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001068 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1069 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001070 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001071
1072 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1073 const ResTable& res = theme->getResTable();
1074 ResTable_config config;
1075 Res_value value;
1076
1077 const jsize NI = env->GetArrayLength(attrs);
1078 const jsize NV = env->GetArrayLength(outValues);
1079 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1080 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1081 return JNI_FALSE;
1082 }
1083
1084 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1085 if (src == NULL) {
1086 return JNI_FALSE;
1087 }
1088
1089 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1090 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1091
1092 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1093 jint* dest = baseDest;
1094 if (dest == NULL) {
1095 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1096 return JNI_FALSE;
1097 }
1098
1099 jint* indices = NULL;
1100 int indicesIdx = 0;
1101 if (outIndices != NULL) {
1102 if (env->GetArrayLength(outIndices) > NI) {
1103 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1104 }
1105 }
1106
1107 // Load default style from attribute, if specified...
1108 uint32_t defStyleBagTypeSetFlags = 0;
1109 if (defStyleAttr != 0) {
1110 Res_value value;
1111 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1112 if (value.dataType == Res_value::TYPE_REFERENCE) {
1113 defStyleRes = value.data;
1114 }
1115 }
1116 }
1117
1118 // Now lock down the resource object and start pulling stuff from it.
1119 res.lock();
1120
1121 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001122 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001123 uint32_t defStyleTypeSetFlags = 0;
1124 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001125 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001126 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001127 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1128 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001129
1130 // Now iterate through all of the attributes that the client has requested,
1131 // filling in each with whatever data we can find.
1132 ssize_t block = 0;
1133 uint32_t typeSetFlags;
1134 for (jsize ii=0; ii<NI; ii++) {
1135 const uint32_t curIdent = (uint32_t)src[ii];
1136
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001137 if (kDebugStyles) {
1138 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1139 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001140
1141 // Try to find a value for this attribute... we prioritize values
1142 // coming from, first XML attributes, then XML style, then default
1143 // style, and finally the theme.
1144 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001145 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001146 typeSetFlags = 0;
1147 config.density = 0;
1148
1149 // Retrieve the current input value if available.
1150 if (NSV > 0 && srcValues[ii] != 0) {
1151 block = -1;
1152 value.dataType = Res_value::TYPE_ATTRIBUTE;
1153 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001154 if (kDebugStyles) {
1155 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1156 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001157 }
1158
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001159 if (value.dataType == Res_value::TYPE_NULL) {
1160 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1161 if (defStyleEntry != defStyleEnd) {
1162 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001164 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001165 if (kDebugStyles) {
1166 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1167 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001168 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001169 }
1170
1171 uint32_t resid = 0;
1172 if (value.dataType != Res_value::TYPE_NULL) {
1173 // Take care of resolving the found resource to its final value.
1174 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1175 &resid, &typeSetFlags, &config);
1176 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001177 if (kDebugStyles) {
1178 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1179 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001180 } else {
1181 // If we still don't have a value for this attribute, try to find
1182 // it in the theme!
1183 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1184 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001185 if (kDebugStyles) {
1186 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1187 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001188 newBlock = res.resolveReference(&value, block, &resid,
1189 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001190 if (kThrowOnBadId) {
1191 if (newBlock == BAD_INDEX) {
1192 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1193 return JNI_FALSE;
1194 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001195 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001196 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001197 if (kDebugStyles) {
1198 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1199 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001200 }
1201 }
1202
1203 // Deal with the special @null value -- it turns back to TYPE_NULL.
1204 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001205 if (kDebugStyles) {
1206 ALOGI("-> Setting to @null!");
1207 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001208 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001209 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001210 block = -1;
1211 }
1212
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001213 if (kDebugStyles) {
1214 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1215 value.data);
1216 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001217
1218 // Write the final value back to Java.
1219 dest[STYLE_TYPE] = value.dataType;
1220 dest[STYLE_DATA] = value.data;
1221 dest[STYLE_ASSET_COOKIE] =
1222 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1223 dest[STYLE_RESOURCE_ID] = resid;
1224 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1225 dest[STYLE_DENSITY] = config.density;
1226
1227 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1228 indicesIdx++;
1229 indices[indicesIdx] = ii;
1230 }
1231
1232 dest += STYLE_NUM_ENTRIES;
1233 }
1234
1235 res.unlock();
1236
1237 if (indices != NULL) {
1238 indices[0] = indicesIdx;
1239 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1240 }
1241 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1242 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1243 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1244
1245 return JNI_TRUE;
1246}
1247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001249 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 jint defStyleAttr,
1251 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001252 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 jintArray attrs,
1254 jintArray outValues,
1255 jintArray outIndices)
1256{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001257 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001258 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001259 return JNI_FALSE;
1260 }
1261 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001262 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001263 return JNI_FALSE;
1264 }
1265 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001266 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 return JNI_FALSE;
1268 }
1269
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001270 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001271 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1272 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1273 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001274 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001275
Ashok Bhat896043d2014-01-17 16:02:38 +00001276 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001278 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001279 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 Res_value value;
1281
1282 const jsize NI = env->GetArrayLength(attrs);
1283 const jsize NV = env->GetArrayLength(outValues);
1284 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001285 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 return JNI_FALSE;
1287 }
1288
1289 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1290 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 return JNI_FALSE;
1292 }
1293
1294 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1295 jint* dest = baseDest;
1296 if (dest == NULL) {
1297 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 return JNI_FALSE;
1299 }
1300
1301 jint* indices = NULL;
1302 int indicesIdx = 0;
1303 if (outIndices != NULL) {
1304 if (env->GetArrayLength(outIndices) > NI) {
1305 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1306 }
1307 }
1308
1309 // Load default style from attribute, if specified...
1310 uint32_t defStyleBagTypeSetFlags = 0;
1311 if (defStyleAttr != 0) {
1312 Res_value value;
1313 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1314 if (value.dataType == Res_value::TYPE_REFERENCE) {
1315 defStyleRes = value.data;
1316 }
1317 }
1318 }
1319
1320 // Retrieve the style class associated with the current XML tag.
1321 int style = 0;
1322 uint32_t styleBagTypeSetFlags = 0;
1323 if (xmlParser != NULL) {
1324 ssize_t idx = xmlParser->indexOfStyle();
1325 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1326 if (value.dataType == value.TYPE_ATTRIBUTE) {
1327 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1328 value.dataType = Res_value::TYPE_NULL;
1329 }
1330 }
1331 if (value.dataType == value.TYPE_REFERENCE) {
1332 style = value.data;
1333 }
1334 }
1335 }
1336
1337 // Now lock down the resource object and start pulling stuff from it.
1338 res.lock();
1339
1340 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001341 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 uint32_t defStyleTypeSetFlags = 0;
1343 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001344 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001346 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1347 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348
1349 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001350 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001352 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001354 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1355 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356
1357 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001359 XmlAttributeFinder xmlAttrFinder(xmlParser);
1360 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361
1362 // Now iterate through all of the attributes that the client has requested,
1363 // filling in each with whatever data we can find.
1364 ssize_t block = 0;
1365 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001366 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 const uint32_t curIdent = (uint32_t)src[ii];
1368
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001369 if (kDebugStyles) {
1370 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1371 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 // Try to find a value for this attribute... we prioritize values
1374 // coming from, first XML attributes, then XML style, then default
1375 // style, and finally the theme.
1376 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001377 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001379 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001381 // Walk through the xml attributes looking for the requested attribute.
1382 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1383 if (xmlAttrIdx != xmlAttrEnd) {
1384 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001386 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001387 if (kDebugStyles) {
1388 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 }
1391
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001392 if (value.dataType == Res_value::TYPE_NULL) {
1393 // Walk through the style class values looking for the requested attribute.
1394 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1395 if (styleAttrEntry != styleAttrEnd) {
1396 // We found the attribute we were looking for.
1397 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001399 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001400 if (kDebugStyles) {
1401 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 }
1405
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001406 if (value.dataType == Res_value::TYPE_NULL) {
1407 // Walk through the default style values looking for the requested attribute.
1408 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1409 if (defStyleAttrEntry != defStyleAttrEnd) {
1410 // We found the attribute we were looking for.
1411 block = defStyleAttrEntry->stringBlock;
1412 typeSetFlags = styleTypeSetFlags;
1413 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001414 if (kDebugStyles) {
1415 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1416 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 }
1419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 uint32_t resid = 0;
1421 if (value.dataType != Res_value::TYPE_NULL) {
1422 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001423 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1424 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001425 if (newBlock >= 0) {
1426 block = newBlock;
1427 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001428
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001429 if (kDebugStyles) {
1430 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1431 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432 } else {
1433 // If we still don't have a value for this attribute, try to find
1434 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1436 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001437 if (kDebugStyles) {
1438 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1439 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001440 newBlock = res.resolveReference(&value, block, &resid,
1441 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001442 if (kThrowOnBadId) {
1443 if (newBlock == BAD_INDEX) {
1444 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1445 return JNI_FALSE;
1446 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001447 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001448
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001449 if (newBlock >= 0) {
1450 block = newBlock;
1451 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001452
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001453 if (kDebugStyles) {
1454 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
1457 }
1458
1459 // Deal with the special @null value -- it turns back to TYPE_NULL.
1460 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001461 if (kDebugStyles) {
1462 ALOGI("-> Setting to @null!");
1463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001465 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001466 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001469 if (kDebugStyles) {
1470 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472
1473 // Write the final value back to Java.
1474 dest[STYLE_TYPE] = value.dataType;
1475 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001476 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1477 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 dest[STYLE_RESOURCE_ID] = resid;
1479 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001480 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1483 indicesIdx++;
1484 indices[indicesIdx] = ii;
1485 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 dest += STYLE_NUM_ENTRIES;
1488 }
1489
1490 res.unlock();
1491
1492 if (indices != NULL) {
1493 indices[0] = indicesIdx;
1494 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1495 }
1496 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1497 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1498
1499 return JNI_TRUE;
1500}
1501
1502static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001503 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 jintArray attrs,
1505 jintArray outValues,
1506 jintArray outIndices)
1507{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001508 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001509 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001510 return JNI_FALSE;
1511 }
1512 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001513 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001514 return JNI_FALSE;
1515 }
1516 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001517 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 return JNI_FALSE;
1519 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 AssetManager* am = assetManagerForJavaObject(env, clazz);
1522 if (am == NULL) {
1523 return JNI_FALSE;
1524 }
1525 const ResTable& res(am->getResources());
1526 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001527 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 const jsize NI = env->GetArrayLength(attrs);
1531 const jsize NV = env->GetArrayLength(outValues);
1532 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001533 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 return JNI_FALSE;
1535 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1538 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 return JNI_FALSE;
1540 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1543 jint* dest = baseDest;
1544 if (dest == NULL) {
1545 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 return JNI_FALSE;
1547 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 jint* indices = NULL;
1550 int indicesIdx = 0;
1551 if (outIndices != NULL) {
1552 if (env->GetArrayLength(outIndices) > NI) {
1553 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1554 }
1555 }
1556
1557 // Now lock down the resource object and start pulling stuff from it.
1558 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 // Retrieve the XML attributes, if requested.
1561 const jsize NX = xmlParser->getAttributeCount();
1562 jsize ix=0;
1563 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // Now iterate through all of the attributes that the client has requested,
1568 // filling in each with whatever data we can find.
1569 ssize_t block = 0;
1570 uint32_t typeSetFlags;
1571 for (jsize ii=0; ii<NI; ii++) {
1572 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 // Try to find a value for this attribute...
1575 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001576 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001578 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001581 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 ix++;
1583 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1584 }
1585 // Retrieve the current XML attribute if it matches, and step to next.
1586 if (ix < NX && curIdent == curXmlAttr) {
1587 block = kXmlBlock;
1588 xmlParser->getAttributeValue(ix, &value);
1589 ix++;
1590 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1591 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1594 uint32_t resid = 0;
1595 if (value.dataType != Res_value::TYPE_NULL) {
1596 // Take care of resolving the found resource to its final value.
1597 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001598 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1599 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001600 if (kThrowOnBadId) {
1601 if (newBlock == BAD_INDEX) {
1602 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1603 return JNI_FALSE;
1604 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001605 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 if (newBlock >= 0) block = newBlock;
1607 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 // Deal with the special @null value -- it turns back to TYPE_NULL.
1610 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1611 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001612 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 // Write the final value back to Java.
1618 dest[STYLE_TYPE] = value.dataType;
1619 dest[STYLE_DATA] = value.data;
1620 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001621 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 dest[STYLE_RESOURCE_ID] = resid;
1623 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001624 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1627 indicesIdx++;
1628 indices[indicesIdx] = ii;
1629 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 dest += STYLE_NUM_ENTRIES;
1632 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 if (indices != NULL) {
1637 indices[0] = indicesIdx;
1638 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1639 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1642 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 return JNI_TRUE;
1645}
1646
1647static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1648 jint id)
1649{
1650 AssetManager* am = assetManagerForJavaObject(env, clazz);
1651 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001652 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 }
1654 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 res.lock();
1657 const ResTable::bag_entry* defStyleEnt = NULL;
1658 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1659 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001660
Ashok Bhat896043d2014-01-17 16:02:38 +00001661 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662}
1663
1664static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1665 jint id,
1666 jintArray outValues)
1667{
1668 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001669 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 return JNI_FALSE;
1671 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 AssetManager* am = assetManagerForJavaObject(env, clazz);
1674 if (am == NULL) {
1675 return JNI_FALSE;
1676 }
1677 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001678 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 Res_value value;
1680 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1685 jint* dest = baseDest;
1686 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001687 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 return JNI_FALSE;
1689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 // Now lock down the resource object and start pulling stuff from it.
1692 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 const ResTable::bag_entry* arrayEnt = NULL;
1695 uint32_t arrayTypeSetFlags = 0;
1696 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1697 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1698 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 int i = 0;
1701 uint32_t typeSetFlags;
1702 while (i < NV && arrayEnt < endArrayEnt) {
1703 block = arrayEnt->stringBlock;
1704 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001705 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 uint32_t resid = 0;
1709 if (value.dataType != Res_value::TYPE_NULL) {
1710 // Take care of resolving the found resource to its final value.
1711 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001712 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1713 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001714 if (kThrowOnBadId) {
1715 if (newBlock == BAD_INDEX) {
1716 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1717 return JNI_FALSE;
1718 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 if (newBlock >= 0) block = newBlock;
1721 }
1722
1723 // Deal with the special @null value -- it turns back to TYPE_NULL.
1724 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1725 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001726 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 }
1728
1729 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1730
1731 // Write the final value back to Java.
1732 dest[STYLE_TYPE] = value.dataType;
1733 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001734 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 dest[STYLE_RESOURCE_ID] = resid;
1736 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001737 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 dest += STYLE_NUM_ENTRIES;
1739 i+= STYLE_NUM_ENTRIES;
1740 arrayEnt++;
1741 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 return i;
1750}
1751
Ashok Bhat896043d2014-01-17 16:02:38 +00001752static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 jint cookie,
1754 jstring fileName)
1755{
1756 AssetManager* am = assetManagerForJavaObject(env, clazz);
1757 if (am == NULL) {
1758 return 0;
1759 }
1760
Steve Block71f2cf12011-10-20 11:56:00 +01001761 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762
Elliott Hughes69a017b2011-04-08 14:10:28 -07001763 ScopedUtfChars fileName8(env, fileName);
1764 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 return 0;
1766 }
1767
Adam Lesinskide898ff2014-01-29 18:20:45 -08001768 int32_t assetCookie = static_cast<int32_t>(cookie);
1769 Asset* a = assetCookie
1770 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1771 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772
1773 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001774 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 return 0;
1776 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777
Adam Lesinskide898ff2014-01-29 18:20:45 -08001778 const DynamicRefTable* dynamicRefTable =
1779 am->getResources().getDynamicRefTableForCookie(assetCookie);
1780 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1782 a->close();
1783 delete a;
1784
1785 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001786 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 return 0;
1788 }
1789
Ashok Bhat896043d2014-01-17 16:02:38 +00001790 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791}
1792
1793static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1794 jint arrayResId)
1795{
1796 AssetManager* am = assetManagerForJavaObject(env, clazz);
1797 if (am == NULL) {
1798 return NULL;
1799 }
1800 const ResTable& res(am->getResources());
1801
1802 const ResTable::bag_entry* startOfBag;
1803 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1804 if (N < 0) {
1805 return NULL;
1806 }
1807
1808 jintArray array = env->NewIntArray(N * 2);
1809 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 res.unlockBag(startOfBag);
1811 return NULL;
1812 }
1813
1814 Res_value value;
1815 const ResTable::bag_entry* bag = startOfBag;
1816 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1817 jint stringIndex = -1;
1818 jint stringBlock = 0;
1819 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 // Take care of resolving the found resource to its final value.
1822 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1823 if (value.dataType == Res_value::TYPE_STRING) {
1824 stringIndex = value.data;
1825 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001826
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001827 if (kThrowOnBadId) {
1828 if (stringBlock == BAD_INDEX) {
1829 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1830 return array;
1831 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001832 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001833
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001834 //todo: It might be faster to allocate a C array to contain
1835 // the blocknums and indices, put them in there and then
1836 // do just one SetIntArrayRegion()
1837 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1838 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1839 j = j + 2;
1840 }
1841 res.unlockBag(startOfBag);
1842 return array;
1843}
1844
1845static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1846 jint arrayResId)
1847{
1848 AssetManager* am = assetManagerForJavaObject(env, clazz);
1849 if (am == NULL) {
1850 return NULL;
1851 }
1852 const ResTable& res(am->getResources());
1853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854 const ResTable::bag_entry* startOfBag;
1855 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1856 if (N < 0) {
1857 return NULL;
1858 }
1859
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001860 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001861 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 res.unlockBag(startOfBag);
1863 return NULL;
1864 }
1865
1866 Res_value value;
1867 const ResTable::bag_entry* bag = startOfBag;
1868 size_t strLen = 0;
1869 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1870 value = bag->map.value;
1871 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 // Take care of resolving the found resource to its final value.
1874 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001875 if (kThrowOnBadId) {
1876 if (block == BAD_INDEX) {
1877 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1878 return array;
1879 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001882 const ResStringPool* pool = res.getTableStringBlock(block);
1883 const char* str8 = pool->string8At(value.data, &strLen);
1884 if (str8 != NULL) {
1885 str = env->NewStringUTF(str8);
1886 } else {
1887 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001888 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1889 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001890 }
1891
1892 // If one of our NewString{UTF} calls failed due to memory, an
1893 // exception will be pending.
1894 if (env->ExceptionCheck()) {
1895 res.unlockBag(startOfBag);
1896 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 }
Kenny Root780d2a12010-02-22 22:36:26 -08001898
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001899 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001900
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001901 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1902 // If we have a large amount of strings in our array, we might
1903 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001904 env->DeleteLocalRef(str);
1905 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 }
1907 res.unlockBag(startOfBag);
1908 return array;
1909}
1910
1911static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1912 jint arrayResId)
1913{
1914 AssetManager* am = assetManagerForJavaObject(env, clazz);
1915 if (am == NULL) {
1916 return NULL;
1917 }
1918 const ResTable& res(am->getResources());
1919
1920 const ResTable::bag_entry* startOfBag;
1921 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1922 if (N < 0) {
1923 return NULL;
1924 }
1925
1926 jintArray array = env->NewIntArray(N);
1927 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 res.unlockBag(startOfBag);
1929 return NULL;
1930 }
1931
1932 Res_value value;
1933 const ResTable::bag_entry* bag = startOfBag;
1934 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1935 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 // Take care of resolving the found resource to its final value.
1938 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001939 if (kThrowOnBadId) {
1940 if (block == BAD_INDEX) {
1941 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1942 return array;
1943 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 if (value.dataType >= Res_value::TYPE_FIRST_INT
1946 && value.dataType <= Res_value::TYPE_LAST_INT) {
1947 int intVal = value.data;
1948 env->SetIntArrayRegion(array, i, 1, &intVal);
1949 }
1950 }
1951 res.unlockBag(startOfBag);
1952 return array;
1953}
1954
Jon Miranda042ad632014-09-03 17:57:35 -07001955static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1956 jint styleId)
1957{
1958 AssetManager* am = assetManagerForJavaObject(env, clazz);
1959 if (am == NULL) {
1960 return NULL;
1961 }
1962 const ResTable& res(am->getResources());
1963
1964 const ResTable::bag_entry* startOfBag;
1965 const ssize_t N = res.lockBag(styleId, &startOfBag);
1966 if (N < 0) {
1967 return NULL;
1968 }
1969
1970 jintArray array = env->NewIntArray(N);
1971 if (array == NULL) {
1972 res.unlockBag(startOfBag);
1973 return NULL;
1974 }
1975
Jon Miranda042ad632014-09-03 17:57:35 -07001976 const ResTable::bag_entry* bag = startOfBag;
1977 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1978 int resourceId = bag->map.name.ident;
1979 env->SetIntArrayRegion(array, i, 1, &resourceId);
1980 }
1981 res.unlockBag(startOfBag);
1982 return array;
1983}
1984
Mårten Kongstad48d22322014-01-31 14:43:27 +01001985static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001987 if (isSystem) {
1988 verifySystemIdmaps();
1989 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 AssetManager* am = new AssetManager();
1991 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001992 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 return;
1994 }
1995
1996 am->addDefaultAssets();
1997
Steve Block71f2cf12011-10-20 11:56:00 +01001998 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001999 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000}
2001
2002static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2003{
2004 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002005 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002006 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 if (am != NULL) {
2008 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002009 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 }
2011}
2012
2013static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2014{
2015 return Asset::getGlobalCount();
2016}
2017
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002018static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2019{
2020 String8 alloc = Asset::getAssetAllocations();
2021 if (alloc.length() <= 0) {
2022 return NULL;
2023 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002024
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002025 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002026 return str;
2027}
2028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2030{
2031 return AssetManager::getGlobalCount();
2032}
2033
2034// ----------------------------------------------------------------------------
2035
2036/*
2037 * JNI registration.
2038 */
2039static JNINativeMethod gAssetManagerMethods[] = {
2040 /* name, signature, funcPtr */
2041
2042 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002043 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 (void*) android_content_AssetManager_openAsset },
2045 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2046 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002047 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 (void*) android_content_AssetManager_openNonAssetNative },
2049 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2050 (void*) android_content_AssetManager_openNonAssetFdNative },
2051 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2052 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002053 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002055 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002057 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002059 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002061 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002063 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002065 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002067 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002068 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 { "isUpToDate", "()Z",
2070 (void*) android_content_AssetManager_isUpToDate },
2071
2072 // Resources.
2073 { "setLocale", "(Ljava/lang/String;)V",
2074 (void*) android_content_AssetManager_setLocale },
2075 { "getLocales", "()[Ljava/lang/String;",
2076 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002077 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 (void*) android_content_AssetManager_setConfiguration },
2079 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2080 (void*) android_content_AssetManager_getResourceIdentifier },
2081 { "getResourceName","(I)Ljava/lang/String;",
2082 (void*) android_content_AssetManager_getResourceName },
2083 { "getResourcePackageName","(I)Ljava/lang/String;",
2084 (void*) android_content_AssetManager_getResourcePackageName },
2085 { "getResourceTypeName","(I)Ljava/lang/String;",
2086 (void*) android_content_AssetManager_getResourceTypeName },
2087 { "getResourceEntryName","(I)Ljava/lang/String;",
2088 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002089 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 (void*) android_content_AssetManager_loadResourceValue },
2091 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2092 (void*) android_content_AssetManager_loadResourceBagValue },
2093 { "getStringBlockCount","()I",
2094 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002095 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 (void*) android_content_AssetManager_getNativeStringBlock },
2097 { "getCookieName","(I)Ljava/lang/String;",
2098 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002099 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2100 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101
2102 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002103 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002105 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002107 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002109 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002111 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 (void*) android_content_AssetManager_loadThemeAttributeValue },
Alan Viverettec1d52792015-05-05 09:49:03 -07002113 { "getThemeChangingConfigurations", "(J)I",
2114 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002115 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002117 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002119 { "resolveAttrs","(JII[I[I[I[I)Z",
2120 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002121 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 (void*) android_content_AssetManager_retrieveAttributes },
2123 { "getArraySize","(I)I",
2124 (void*) android_content_AssetManager_getArraySize },
2125 { "retrieveArray","(I[I)I",
2126 (void*) android_content_AssetManager_retrieveArray },
2127
2128 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002129 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 (void*) android_content_AssetManager_openXmlAssetNative },
2131
2132 // Arrays.
2133 { "getArrayStringResource","(I)[Ljava/lang/String;",
2134 (void*) android_content_AssetManager_getArrayStringResource },
2135 { "getArrayStringInfo","(I)[I",
2136 (void*) android_content_AssetManager_getArrayStringInfo },
2137 { "getArrayIntResource","(I)[I",
2138 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002139 { "getStyleAttributes","(I)[I",
2140 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141
2142 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002143 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 (void*) android_content_AssetManager_init },
2145 { "destroy", "()V",
2146 (void*) android_content_AssetManager_destroy },
2147 { "getGlobalAssetCount", "()I",
2148 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002149 { "getAssetAllocations", "()Ljava/lang/String;",
2150 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002152 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153};
2154
2155int register_android_content_AssetManager(JNIEnv* env)
2156{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002157 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2158 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2159 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2160 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2161 "Ljava/lang/CharSequence;");
2162 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2163 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2164 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2165 "changingConfigurations", "I");
2166 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167
Andreas Gampe987f79f2014-11-18 17:29:46 -08002168 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2169 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2170 "Landroid/os/ParcelFileDescriptor;");
2171 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2172 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002173
Andreas Gampe987f79f2014-11-18 17:29:46 -08002174 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2175 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176
Andreas Gampe987f79f2014-11-18 17:29:46 -08002177 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2178 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179
Andreas Gampe987f79f2014-11-18 17:29:46 -08002180 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2181 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2182 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2183 "<init>", "()V");
2184 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2185 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002186
Andreas Gampe987f79f2014-11-18 17:29:46 -08002187 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2188 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002189}
2190
2191}; // namespace android