blob: 459cbd115475ceef82eb644ebe2ea69776b5d109 [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
1002static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001003 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 jstring tag, jstring prefix)
1005{
Ashok Bhat896043d2014-01-17 16:02:38 +00001006 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001008 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 // XXX Need to use params.
1011 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012}
1013
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001014class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1015public:
1016 XmlAttributeFinder(const ResXMLParser* parser)
1017 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1018 , mParser(parser) {}
1019
1020 inline uint32_t getAttribute(jsize index) const {
1021 return mParser->getAttributeNameResID(index);
1022 }
1023
1024private:
1025 const ResXMLParser* mParser;
1026};
1027
1028class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1029public:
1030 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1031 : BackTrackingAttributeFinder(start, end) {}
1032
1033 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1034 return entry->map.name.ident;
1035 }
1036};
1037
Alan Viverette52b999f2014-03-24 18:00:26 -07001038static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1039 jlong themeToken,
1040 jint defStyleAttr,
1041 jint defStyleRes,
1042 jintArray inValues,
1043 jintArray attrs,
1044 jintArray outValues,
1045 jintArray outIndices)
1046{
1047 if (themeToken == 0) {
1048 jniThrowNullPointerException(env, "theme token");
1049 return JNI_FALSE;
1050 }
1051 if (attrs == NULL) {
1052 jniThrowNullPointerException(env, "attrs");
1053 return JNI_FALSE;
1054 }
1055 if (outValues == NULL) {
1056 jniThrowNullPointerException(env, "out values");
1057 return JNI_FALSE;
1058 }
1059
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001060 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001061 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1062 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001063 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001064
1065 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1066 const ResTable& res = theme->getResTable();
1067 ResTable_config config;
1068 Res_value value;
1069
1070 const jsize NI = env->GetArrayLength(attrs);
1071 const jsize NV = env->GetArrayLength(outValues);
1072 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1073 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1074 return JNI_FALSE;
1075 }
1076
1077 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1078 if (src == NULL) {
1079 return JNI_FALSE;
1080 }
1081
1082 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1083 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1084
1085 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1086 jint* dest = baseDest;
1087 if (dest == NULL) {
1088 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1089 return JNI_FALSE;
1090 }
1091
1092 jint* indices = NULL;
1093 int indicesIdx = 0;
1094 if (outIndices != NULL) {
1095 if (env->GetArrayLength(outIndices) > NI) {
1096 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1097 }
1098 }
1099
1100 // Load default style from attribute, if specified...
1101 uint32_t defStyleBagTypeSetFlags = 0;
1102 if (defStyleAttr != 0) {
1103 Res_value value;
1104 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1105 if (value.dataType == Res_value::TYPE_REFERENCE) {
1106 defStyleRes = value.data;
1107 }
1108 }
1109 }
1110
1111 // Now lock down the resource object and start pulling stuff from it.
1112 res.lock();
1113
1114 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001115 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001116 uint32_t defStyleTypeSetFlags = 0;
1117 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001118 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001119 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001120 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1121 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001122
1123 // Now iterate through all of the attributes that the client has requested,
1124 // filling in each with whatever data we can find.
1125 ssize_t block = 0;
1126 uint32_t typeSetFlags;
1127 for (jsize ii=0; ii<NI; ii++) {
1128 const uint32_t curIdent = (uint32_t)src[ii];
1129
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001130 if (kDebugStyles) {
1131 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1132 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001133
1134 // Try to find a value for this attribute... we prioritize values
1135 // coming from, first XML attributes, then XML style, then default
1136 // style, and finally the theme.
1137 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001138 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001139 typeSetFlags = 0;
1140 config.density = 0;
1141
1142 // Retrieve the current input value if available.
1143 if (NSV > 0 && srcValues[ii] != 0) {
1144 block = -1;
1145 value.dataType = Res_value::TYPE_ATTRIBUTE;
1146 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001147 if (kDebugStyles) {
1148 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1149 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001150 }
1151
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001152 if (value.dataType == Res_value::TYPE_NULL) {
1153 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1154 if (defStyleEntry != defStyleEnd) {
1155 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001156 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001157 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001158 if (kDebugStyles) {
1159 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1160 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001161 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001162 }
1163
1164 uint32_t resid = 0;
1165 if (value.dataType != Res_value::TYPE_NULL) {
1166 // Take care of resolving the found resource to its final value.
1167 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1168 &resid, &typeSetFlags, &config);
1169 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001170 if (kDebugStyles) {
1171 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1172 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001173 } else {
1174 // If we still don't have a value for this attribute, try to find
1175 // it in the theme!
1176 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1177 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001178 if (kDebugStyles) {
1179 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1180 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001181 newBlock = res.resolveReference(&value, block, &resid,
1182 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001183 if (kThrowOnBadId) {
1184 if (newBlock == BAD_INDEX) {
1185 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1186 return JNI_FALSE;
1187 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001188 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001189 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001190 if (kDebugStyles) {
1191 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1192 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001193 }
1194 }
1195
1196 // Deal with the special @null value -- it turns back to TYPE_NULL.
1197 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001198 if (kDebugStyles) {
1199 ALOGI("-> Setting to @null!");
1200 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001201 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001202 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001203 block = -1;
1204 }
1205
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001206 if (kDebugStyles) {
1207 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1208 value.data);
1209 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001210
1211 // Write the final value back to Java.
1212 dest[STYLE_TYPE] = value.dataType;
1213 dest[STYLE_DATA] = value.data;
1214 dest[STYLE_ASSET_COOKIE] =
1215 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1216 dest[STYLE_RESOURCE_ID] = resid;
1217 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1218 dest[STYLE_DENSITY] = config.density;
1219
1220 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1221 indicesIdx++;
1222 indices[indicesIdx] = ii;
1223 }
1224
1225 dest += STYLE_NUM_ENTRIES;
1226 }
1227
1228 res.unlock();
1229
1230 if (indices != NULL) {
1231 indices[0] = indicesIdx;
1232 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1233 }
1234 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1235 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1236 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1237
1238 return JNI_TRUE;
1239}
1240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001242 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 jint defStyleAttr,
1244 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001245 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 jintArray attrs,
1247 jintArray outValues,
1248 jintArray outIndices)
1249{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001250 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001251 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001252 return JNI_FALSE;
1253 }
1254 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001255 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001256 return JNI_FALSE;
1257 }
1258 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001259 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 return JNI_FALSE;
1261 }
1262
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001263 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001264 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1265 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1266 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001267 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001268
Ashok Bhat896043d2014-01-17 16:02:38 +00001269 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001271 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001272 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 Res_value value;
1274
1275 const jsize NI = env->GetArrayLength(attrs);
1276 const jsize NV = env->GetArrayLength(outValues);
1277 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001278 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 return JNI_FALSE;
1280 }
1281
1282 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1283 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 return JNI_FALSE;
1285 }
1286
1287 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1288 jint* dest = baseDest;
1289 if (dest == NULL) {
1290 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 return JNI_FALSE;
1292 }
1293
1294 jint* indices = NULL;
1295 int indicesIdx = 0;
1296 if (outIndices != NULL) {
1297 if (env->GetArrayLength(outIndices) > NI) {
1298 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1299 }
1300 }
1301
1302 // Load default style from attribute, if specified...
1303 uint32_t defStyleBagTypeSetFlags = 0;
1304 if (defStyleAttr != 0) {
1305 Res_value value;
1306 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1307 if (value.dataType == Res_value::TYPE_REFERENCE) {
1308 defStyleRes = value.data;
1309 }
1310 }
1311 }
1312
1313 // Retrieve the style class associated with the current XML tag.
1314 int style = 0;
1315 uint32_t styleBagTypeSetFlags = 0;
1316 if (xmlParser != NULL) {
1317 ssize_t idx = xmlParser->indexOfStyle();
1318 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1319 if (value.dataType == value.TYPE_ATTRIBUTE) {
1320 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1321 value.dataType = Res_value::TYPE_NULL;
1322 }
1323 }
1324 if (value.dataType == value.TYPE_REFERENCE) {
1325 style = value.data;
1326 }
1327 }
1328 }
1329
1330 // Now lock down the resource object and start pulling stuff from it.
1331 res.lock();
1332
1333 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001334 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 uint32_t defStyleTypeSetFlags = 0;
1336 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001337 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001339 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1340 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341
1342 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001343 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001345 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001347 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1348 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349
1350 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001352 XmlAttributeFinder xmlAttrFinder(xmlParser);
1353 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354
1355 // Now iterate through all of the attributes that the client has requested,
1356 // filling in each with whatever data we can find.
1357 ssize_t block = 0;
1358 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001359 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 const uint32_t curIdent = (uint32_t)src[ii];
1361
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001362 if (kDebugStyles) {
1363 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1364 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 // Try to find a value for this attribute... we prioritize values
1367 // coming from, first XML attributes, then XML style, then default
1368 // style, and finally the theme.
1369 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001370 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001372 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001374 // Walk through the xml attributes looking for the requested attribute.
1375 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1376 if (xmlAttrIdx != xmlAttrEnd) {
1377 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001379 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001380 if (kDebugStyles) {
1381 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 }
1384
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001385 if (value.dataType == Res_value::TYPE_NULL) {
1386 // Walk through the style class values looking for the requested attribute.
1387 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1388 if (styleAttrEntry != styleAttrEnd) {
1389 // We found the attribute we were looking for.
1390 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001392 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001393 if (kDebugStyles) {
1394 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001399 if (value.dataType == Res_value::TYPE_NULL) {
1400 // Walk through the default style values looking for the requested attribute.
1401 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1402 if (defStyleAttrEntry != defStyleAttrEnd) {
1403 // We found the attribute we were looking for.
1404 block = defStyleAttrEntry->stringBlock;
1405 typeSetFlags = styleTypeSetFlags;
1406 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001407 if (kDebugStyles) {
1408 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 uint32_t resid = 0;
1414 if (value.dataType != Res_value::TYPE_NULL) {
1415 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001416 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1417 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001418 if (newBlock >= 0) {
1419 block = newBlock;
1420 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001421
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001422 if (kDebugStyles) {
1423 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 } else {
1426 // If we still don't have a value for this attribute, try to find
1427 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1429 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001430 if (kDebugStyles) {
1431 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1432 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001433 newBlock = res.resolveReference(&value, block, &resid,
1434 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001435 if (kThrowOnBadId) {
1436 if (newBlock == BAD_INDEX) {
1437 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1438 return JNI_FALSE;
1439 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001440 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001441
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001442 if (newBlock >= 0) {
1443 block = newBlock;
1444 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001445
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001446 if (kDebugStyles) {
1447 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450 }
1451
1452 // Deal with the special @null value -- it turns back to TYPE_NULL.
1453 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001454 if (kDebugStyles) {
1455 ALOGI("-> Setting to @null!");
1456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001458 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001459 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
1461
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001462 if (kDebugStyles) {
1463 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465
1466 // Write the final value back to Java.
1467 dest[STYLE_TYPE] = value.dataType;
1468 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001469 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1470 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 dest[STYLE_RESOURCE_ID] = resid;
1472 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001473 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1476 indicesIdx++;
1477 indices[indicesIdx] = ii;
1478 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 dest += STYLE_NUM_ENTRIES;
1481 }
1482
1483 res.unlock();
1484
1485 if (indices != NULL) {
1486 indices[0] = indicesIdx;
1487 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1488 }
1489 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1490 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1491
1492 return JNI_TRUE;
1493}
1494
1495static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001496 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 jintArray attrs,
1498 jintArray outValues,
1499 jintArray outIndices)
1500{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001501 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001502 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001503 return JNI_FALSE;
1504 }
1505 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001506 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001507 return JNI_FALSE;
1508 }
1509 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001510 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 return JNI_FALSE;
1512 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 AssetManager* am = assetManagerForJavaObject(env, clazz);
1515 if (am == NULL) {
1516 return JNI_FALSE;
1517 }
1518 const ResTable& res(am->getResources());
1519 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001520 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 const jsize NI = env->GetArrayLength(attrs);
1524 const jsize NV = env->GetArrayLength(outValues);
1525 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001526 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 return JNI_FALSE;
1528 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1531 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 return JNI_FALSE;
1533 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1536 jint* dest = baseDest;
1537 if (dest == NULL) {
1538 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
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* indices = NULL;
1543 int indicesIdx = 0;
1544 if (outIndices != NULL) {
1545 if (env->GetArrayLength(outIndices) > NI) {
1546 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1547 }
1548 }
1549
1550 // Now lock down the resource object and start pulling stuff from it.
1551 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 // Retrieve the XML attributes, if requested.
1554 const jsize NX = xmlParser->getAttributeCount();
1555 jsize ix=0;
1556 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 // Now iterate through all of the attributes that the client has requested,
1561 // filling in each with whatever data we can find.
1562 ssize_t block = 0;
1563 uint32_t typeSetFlags;
1564 for (jsize ii=0; ii<NI; ii++) {
1565 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // Try to find a value for this attribute...
1568 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001569 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001571 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001574 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 ix++;
1576 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1577 }
1578 // Retrieve the current XML attribute if it matches, and step to next.
1579 if (ix < NX && curIdent == curXmlAttr) {
1580 block = kXmlBlock;
1581 xmlParser->getAttributeValue(ix, &value);
1582 ix++;
1583 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1584 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1587 uint32_t resid = 0;
1588 if (value.dataType != Res_value::TYPE_NULL) {
1589 // Take care of resolving the found resource to its final value.
1590 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001591 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1592 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001593 if (kThrowOnBadId) {
1594 if (newBlock == BAD_INDEX) {
1595 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1596 return JNI_FALSE;
1597 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 if (newBlock >= 0) block = newBlock;
1600 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 // Deal with the special @null value -- it turns back to TYPE_NULL.
1603 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1604 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001605 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 // Write the final value back to Java.
1611 dest[STYLE_TYPE] = value.dataType;
1612 dest[STYLE_DATA] = value.data;
1613 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001614 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 dest[STYLE_RESOURCE_ID] = resid;
1616 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001617 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1620 indicesIdx++;
1621 indices[indicesIdx] = ii;
1622 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 dest += STYLE_NUM_ENTRIES;
1625 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 if (indices != NULL) {
1630 indices[0] = indicesIdx;
1631 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1632 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1635 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return JNI_TRUE;
1638}
1639
1640static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1641 jint id)
1642{
1643 AssetManager* am = assetManagerForJavaObject(env, clazz);
1644 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001645 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 }
1647 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 res.lock();
1650 const ResTable::bag_entry* defStyleEnt = NULL;
1651 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1652 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001653
Ashok Bhat896043d2014-01-17 16:02:38 +00001654 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655}
1656
1657static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1658 jint id,
1659 jintArray outValues)
1660{
1661 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001662 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 return JNI_FALSE;
1664 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 AssetManager* am = assetManagerForJavaObject(env, clazz);
1667 if (am == NULL) {
1668 return JNI_FALSE;
1669 }
1670 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001671 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 Res_value value;
1673 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1678 jint* dest = baseDest;
1679 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001680 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 return JNI_FALSE;
1682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 // Now lock down the resource object and start pulling stuff from it.
1685 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 const ResTable::bag_entry* arrayEnt = NULL;
1688 uint32_t arrayTypeSetFlags = 0;
1689 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1690 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1691 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 int i = 0;
1694 uint32_t typeSetFlags;
1695 while (i < NV && arrayEnt < endArrayEnt) {
1696 block = arrayEnt->stringBlock;
1697 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001698 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 uint32_t resid = 0;
1702 if (value.dataType != Res_value::TYPE_NULL) {
1703 // Take care of resolving the found resource to its final value.
1704 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001705 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1706 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001707 if (kThrowOnBadId) {
1708 if (newBlock == BAD_INDEX) {
1709 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1710 return JNI_FALSE;
1711 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 if (newBlock >= 0) block = newBlock;
1714 }
1715
1716 // Deal with the special @null value -- it turns back to TYPE_NULL.
1717 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1718 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001719 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 }
1721
1722 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1723
1724 // Write the final value back to Java.
1725 dest[STYLE_TYPE] = value.dataType;
1726 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001727 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 dest[STYLE_RESOURCE_ID] = resid;
1729 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001730 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 dest += STYLE_NUM_ENTRIES;
1732 i+= STYLE_NUM_ENTRIES;
1733 arrayEnt++;
1734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 return i;
1743}
1744
Ashok Bhat896043d2014-01-17 16:02:38 +00001745static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 jint cookie,
1747 jstring fileName)
1748{
1749 AssetManager* am = assetManagerForJavaObject(env, clazz);
1750 if (am == NULL) {
1751 return 0;
1752 }
1753
Steve Block71f2cf12011-10-20 11:56:00 +01001754 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755
Elliott Hughes69a017b2011-04-08 14:10:28 -07001756 ScopedUtfChars fileName8(env, fileName);
1757 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 return 0;
1759 }
1760
Adam Lesinskide898ff2014-01-29 18:20:45 -08001761 int32_t assetCookie = static_cast<int32_t>(cookie);
1762 Asset* a = assetCookie
1763 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1764 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765
1766 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001767 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 return 0;
1769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770
Adam Lesinskide898ff2014-01-29 18:20:45 -08001771 const DynamicRefTable* dynamicRefTable =
1772 am->getResources().getDynamicRefTableForCookie(assetCookie);
1773 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1775 a->close();
1776 delete a;
1777
1778 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001779 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 return 0;
1781 }
1782
Ashok Bhat896043d2014-01-17 16:02:38 +00001783 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784}
1785
1786static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1787 jint arrayResId)
1788{
1789 AssetManager* am = assetManagerForJavaObject(env, clazz);
1790 if (am == NULL) {
1791 return NULL;
1792 }
1793 const ResTable& res(am->getResources());
1794
1795 const ResTable::bag_entry* startOfBag;
1796 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1797 if (N < 0) {
1798 return NULL;
1799 }
1800
1801 jintArray array = env->NewIntArray(N * 2);
1802 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 res.unlockBag(startOfBag);
1804 return NULL;
1805 }
1806
1807 Res_value value;
1808 const ResTable::bag_entry* bag = startOfBag;
1809 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1810 jint stringIndex = -1;
1811 jint stringBlock = 0;
1812 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 // Take care of resolving the found resource to its final value.
1815 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1816 if (value.dataType == Res_value::TYPE_STRING) {
1817 stringIndex = value.data;
1818 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001819
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001820 if (kThrowOnBadId) {
1821 if (stringBlock == BAD_INDEX) {
1822 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1823 return array;
1824 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001825 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 //todo: It might be faster to allocate a C array to contain
1828 // the blocknums and indices, put them in there and then
1829 // do just one SetIntArrayRegion()
1830 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1831 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1832 j = j + 2;
1833 }
1834 res.unlockBag(startOfBag);
1835 return array;
1836}
1837
1838static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1839 jint arrayResId)
1840{
1841 AssetManager* am = assetManagerForJavaObject(env, clazz);
1842 if (am == NULL) {
1843 return NULL;
1844 }
1845 const ResTable& res(am->getResources());
1846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 const ResTable::bag_entry* startOfBag;
1848 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1849 if (N < 0) {
1850 return NULL;
1851 }
1852
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001853 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001854 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 res.unlockBag(startOfBag);
1856 return NULL;
1857 }
1858
1859 Res_value value;
1860 const ResTable::bag_entry* bag = startOfBag;
1861 size_t strLen = 0;
1862 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1863 value = bag->map.value;
1864 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 // Take care of resolving the found resource to its final value.
1867 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001868 if (kThrowOnBadId) {
1869 if (block == BAD_INDEX) {
1870 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1871 return array;
1872 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001875 const ResStringPool* pool = res.getTableStringBlock(block);
1876 const char* str8 = pool->string8At(value.data, &strLen);
1877 if (str8 != NULL) {
1878 str = env->NewStringUTF(str8);
1879 } else {
1880 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001881 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1882 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001883 }
1884
1885 // If one of our NewString{UTF} calls failed due to memory, an
1886 // exception will be pending.
1887 if (env->ExceptionCheck()) {
1888 res.unlockBag(startOfBag);
1889 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 }
Kenny Root780d2a12010-02-22 22:36:26 -08001891
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001892 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001893
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001894 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1895 // If we have a large amount of strings in our array, we might
1896 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001897 env->DeleteLocalRef(str);
1898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 }
1900 res.unlockBag(startOfBag);
1901 return array;
1902}
1903
1904static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1905 jint arrayResId)
1906{
1907 AssetManager* am = assetManagerForJavaObject(env, clazz);
1908 if (am == NULL) {
1909 return NULL;
1910 }
1911 const ResTable& res(am->getResources());
1912
1913 const ResTable::bag_entry* startOfBag;
1914 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1915 if (N < 0) {
1916 return NULL;
1917 }
1918
1919 jintArray array = env->NewIntArray(N);
1920 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 res.unlockBag(startOfBag);
1922 return NULL;
1923 }
1924
1925 Res_value value;
1926 const ResTable::bag_entry* bag = startOfBag;
1927 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1928 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 // Take care of resolving the found resource to its final value.
1931 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001932 if (kThrowOnBadId) {
1933 if (block == BAD_INDEX) {
1934 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1935 return array;
1936 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 if (value.dataType >= Res_value::TYPE_FIRST_INT
1939 && value.dataType <= Res_value::TYPE_LAST_INT) {
1940 int intVal = value.data;
1941 env->SetIntArrayRegion(array, i, 1, &intVal);
1942 }
1943 }
1944 res.unlockBag(startOfBag);
1945 return array;
1946}
1947
Jon Miranda042ad632014-09-03 17:57:35 -07001948static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1949 jint styleId)
1950{
1951 AssetManager* am = assetManagerForJavaObject(env, clazz);
1952 if (am == NULL) {
1953 return NULL;
1954 }
1955 const ResTable& res(am->getResources());
1956
1957 const ResTable::bag_entry* startOfBag;
1958 const ssize_t N = res.lockBag(styleId, &startOfBag);
1959 if (N < 0) {
1960 return NULL;
1961 }
1962
1963 jintArray array = env->NewIntArray(N);
1964 if (array == NULL) {
1965 res.unlockBag(startOfBag);
1966 return NULL;
1967 }
1968
Jon Miranda042ad632014-09-03 17:57:35 -07001969 const ResTable::bag_entry* bag = startOfBag;
1970 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1971 int resourceId = bag->map.name.ident;
1972 env->SetIntArrayRegion(array, i, 1, &resourceId);
1973 }
1974 res.unlockBag(startOfBag);
1975 return array;
1976}
1977
Mårten Kongstad48d22322014-01-31 14:43:27 +01001978static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001980 if (isSystem) {
1981 verifySystemIdmaps();
1982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 AssetManager* am = new AssetManager();
1984 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001985 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 return;
1987 }
1988
1989 am->addDefaultAssets();
1990
Steve Block71f2cf12011-10-20 11:56:00 +01001991 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001992 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993}
1994
1995static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1996{
1997 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001998 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001999 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 if (am != NULL) {
2001 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002002 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 }
2004}
2005
2006static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2007{
2008 return Asset::getGlobalCount();
2009}
2010
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002011static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2012{
2013 String8 alloc = Asset::getAssetAllocations();
2014 if (alloc.length() <= 0) {
2015 return NULL;
2016 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002017
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002018 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002019 return str;
2020}
2021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2023{
2024 return AssetManager::getGlobalCount();
2025}
2026
2027// ----------------------------------------------------------------------------
2028
2029/*
2030 * JNI registration.
2031 */
2032static JNINativeMethod gAssetManagerMethods[] = {
2033 /* name, signature, funcPtr */
2034
2035 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002036 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 (void*) android_content_AssetManager_openAsset },
2038 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2039 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002040 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_openNonAssetNative },
2042 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2043 (void*) android_content_AssetManager_openNonAssetFdNative },
2044 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2045 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002046 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002048 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002050 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002052 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002054 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002056 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002058 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002060 { "addOverlayPath", "(Ljava/lang/String;)I",
2061 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 { "isUpToDate", "()Z",
2063 (void*) android_content_AssetManager_isUpToDate },
2064
2065 // Resources.
2066 { "setLocale", "(Ljava/lang/String;)V",
2067 (void*) android_content_AssetManager_setLocale },
2068 { "getLocales", "()[Ljava/lang/String;",
2069 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002070 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_setConfiguration },
2072 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2073 (void*) android_content_AssetManager_getResourceIdentifier },
2074 { "getResourceName","(I)Ljava/lang/String;",
2075 (void*) android_content_AssetManager_getResourceName },
2076 { "getResourcePackageName","(I)Ljava/lang/String;",
2077 (void*) android_content_AssetManager_getResourcePackageName },
2078 { "getResourceTypeName","(I)Ljava/lang/String;",
2079 (void*) android_content_AssetManager_getResourceTypeName },
2080 { "getResourceEntryName","(I)Ljava/lang/String;",
2081 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002082 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_loadResourceValue },
2084 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2085 (void*) android_content_AssetManager_loadResourceBagValue },
2086 { "getStringBlockCount","()I",
2087 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002088 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 (void*) android_content_AssetManager_getNativeStringBlock },
2090 { "getCookieName","(I)Ljava/lang/String;",
2091 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002092 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2093 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094
2095 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002096 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002098 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002100 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002102 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002104 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002106 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002108 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002110 { "resolveAttrs","(JII[I[I[I[I)Z",
2111 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002112 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 (void*) android_content_AssetManager_retrieveAttributes },
2114 { "getArraySize","(I)I",
2115 (void*) android_content_AssetManager_getArraySize },
2116 { "retrieveArray","(I[I)I",
2117 (void*) android_content_AssetManager_retrieveArray },
2118
2119 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002120 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 (void*) android_content_AssetManager_openXmlAssetNative },
2122
2123 // Arrays.
2124 { "getArrayStringResource","(I)[Ljava/lang/String;",
2125 (void*) android_content_AssetManager_getArrayStringResource },
2126 { "getArrayStringInfo","(I)[I",
2127 (void*) android_content_AssetManager_getArrayStringInfo },
2128 { "getArrayIntResource","(I)[I",
2129 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002130 { "getStyleAttributes","(I)[I",
2131 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132
2133 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002134 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 (void*) android_content_AssetManager_init },
2136 { "destroy", "()V",
2137 (void*) android_content_AssetManager_destroy },
2138 { "getGlobalAssetCount", "()I",
2139 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002140 { "getAssetAllocations", "()Ljava/lang/String;",
2141 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002143 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144};
2145
2146int register_android_content_AssetManager(JNIEnv* env)
2147{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002148 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2149 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2150 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2151 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2152 "Ljava/lang/CharSequence;");
2153 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2154 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2155 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2156 "changingConfigurations", "I");
2157 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158
Andreas Gampe987f79f2014-11-18 17:29:46 -08002159 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2160 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2161 "Landroid/os/ParcelFileDescriptor;");
2162 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2163 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164
Andreas Gampe987f79f2014-11-18 17:29:46 -08002165 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2166 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167
Andreas Gampe987f79f2014-11-18 17:29:46 -08002168 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2169 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170
Andreas Gampe987f79f2014-11-18 17:29:46 -08002171 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2172 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2173 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2174 "<init>", "()V");
2175 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2176 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002177
Andreas Gampe987f79f2014-11-18 17:29:46 -08002178 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2179 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180}
2181
2182}; // namespace android