blob: 74a9e4e2d16268957b063b4688292ce78464687c [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
Alan Viverettee54d2452015-05-06 10:41:43 -0700979static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
980{
981 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
982 theme->clear();
983}
984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000986 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987{
Ashok Bhat896043d2014-01-17 16:02:38 +0000988 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 const ResTable& res(theme->getResTable());
990
991 Res_value value;
992 // XXX value could be different in different configs!
993 uint32_t typeSpecFlags = 0;
994 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
995 uint32_t ref = 0;
996 if (resolve) {
997 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800998 if (kThrowOnBadId) {
999 if (block == BAD_INDEX) {
1000 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1001 return 0;
1002 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 }
1005 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1006}
1007
Alan Viverettec1d52792015-05-05 09:49:03 -07001008static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1009 jlong themeHandle)
1010{
1011 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1012 return theme->getChangingConfigurations();
1013}
1014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001016 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 jstring tag, jstring prefix)
1018{
Ashok Bhat896043d2014-01-17 16:02:38 +00001019 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001021 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 // XXX Need to use params.
1024 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025}
1026
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001027class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1028public:
1029 XmlAttributeFinder(const ResXMLParser* parser)
1030 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1031 , mParser(parser) {}
1032
1033 inline uint32_t getAttribute(jsize index) const {
1034 return mParser->getAttributeNameResID(index);
1035 }
1036
1037private:
1038 const ResXMLParser* mParser;
1039};
1040
1041class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1042public:
1043 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1044 : BackTrackingAttributeFinder(start, end) {}
1045
1046 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1047 return entry->map.name.ident;
1048 }
1049};
1050
Alan Viverette52b999f2014-03-24 18:00:26 -07001051static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1052 jlong themeToken,
1053 jint defStyleAttr,
1054 jint defStyleRes,
1055 jintArray inValues,
1056 jintArray attrs,
1057 jintArray outValues,
1058 jintArray outIndices)
1059{
1060 if (themeToken == 0) {
1061 jniThrowNullPointerException(env, "theme token");
1062 return JNI_FALSE;
1063 }
1064 if (attrs == NULL) {
1065 jniThrowNullPointerException(env, "attrs");
1066 return JNI_FALSE;
1067 }
1068 if (outValues == NULL) {
1069 jniThrowNullPointerException(env, "out values");
1070 return JNI_FALSE;
1071 }
1072
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001073 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001074 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1075 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001076 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001077
1078 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1079 const ResTable& res = theme->getResTable();
1080 ResTable_config config;
1081 Res_value value;
1082
1083 const jsize NI = env->GetArrayLength(attrs);
1084 const jsize NV = env->GetArrayLength(outValues);
1085 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1086 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1087 return JNI_FALSE;
1088 }
1089
1090 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1091 if (src == NULL) {
1092 return JNI_FALSE;
1093 }
1094
1095 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1096 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1097
1098 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1099 jint* dest = baseDest;
1100 if (dest == NULL) {
1101 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1102 return JNI_FALSE;
1103 }
1104
1105 jint* indices = NULL;
1106 int indicesIdx = 0;
1107 if (outIndices != NULL) {
1108 if (env->GetArrayLength(outIndices) > NI) {
1109 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1110 }
1111 }
1112
1113 // Load default style from attribute, if specified...
1114 uint32_t defStyleBagTypeSetFlags = 0;
1115 if (defStyleAttr != 0) {
1116 Res_value value;
1117 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1118 if (value.dataType == Res_value::TYPE_REFERENCE) {
1119 defStyleRes = value.data;
1120 }
1121 }
1122 }
1123
1124 // Now lock down the resource object and start pulling stuff from it.
1125 res.lock();
1126
1127 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001128 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001129 uint32_t defStyleTypeSetFlags = 0;
1130 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001131 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001132 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001133 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1134 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001135
1136 // Now iterate through all of the attributes that the client has requested,
1137 // filling in each with whatever data we can find.
1138 ssize_t block = 0;
1139 uint32_t typeSetFlags;
1140 for (jsize ii=0; ii<NI; ii++) {
1141 const uint32_t curIdent = (uint32_t)src[ii];
1142
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001143 if (kDebugStyles) {
1144 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1145 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001146
1147 // Try to find a value for this attribute... we prioritize values
1148 // coming from, first XML attributes, then XML style, then default
1149 // style, and finally the theme.
1150 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001151 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001152 typeSetFlags = 0;
1153 config.density = 0;
1154
1155 // Retrieve the current input value if available.
1156 if (NSV > 0 && srcValues[ii] != 0) {
1157 block = -1;
1158 value.dataType = Res_value::TYPE_ATTRIBUTE;
1159 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001160 if (kDebugStyles) {
1161 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1162 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 }
1164
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001165 if (value.dataType == Res_value::TYPE_NULL) {
1166 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1167 if (defStyleEntry != defStyleEnd) {
1168 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001169 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001170 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001171 if (kDebugStyles) {
1172 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1173 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001174 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001175 }
1176
1177 uint32_t resid = 0;
1178 if (value.dataType != Res_value::TYPE_NULL) {
1179 // Take care of resolving the found resource to its final value.
1180 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1181 &resid, &typeSetFlags, &config);
1182 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001183 if (kDebugStyles) {
1184 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1185 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001186 } else {
1187 // If we still don't have a value for this attribute, try to find
1188 // it in the theme!
1189 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1190 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001191 if (kDebugStyles) {
1192 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1193 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001194 newBlock = res.resolveReference(&value, block, &resid,
1195 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001196 if (kThrowOnBadId) {
1197 if (newBlock == BAD_INDEX) {
1198 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1199 return JNI_FALSE;
1200 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001201 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001202 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001203 if (kDebugStyles) {
1204 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1205 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001206 }
1207 }
1208
1209 // Deal with the special @null value -- it turns back to TYPE_NULL.
1210 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001211 if (kDebugStyles) {
1212 ALOGI("-> Setting to @null!");
1213 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001214 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001215 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001216 block = -1;
1217 }
1218
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001219 if (kDebugStyles) {
1220 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1221 value.data);
1222 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001223
1224 // Write the final value back to Java.
1225 dest[STYLE_TYPE] = value.dataType;
1226 dest[STYLE_DATA] = value.data;
1227 dest[STYLE_ASSET_COOKIE] =
1228 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1229 dest[STYLE_RESOURCE_ID] = resid;
1230 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1231 dest[STYLE_DENSITY] = config.density;
1232
1233 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1234 indicesIdx++;
1235 indices[indicesIdx] = ii;
1236 }
1237
1238 dest += STYLE_NUM_ENTRIES;
1239 }
1240
1241 res.unlock();
1242
1243 if (indices != NULL) {
1244 indices[0] = indicesIdx;
1245 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1246 }
1247 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1248 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1249 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1250
1251 return JNI_TRUE;
1252}
1253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001255 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 jint defStyleAttr,
1257 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001258 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 jintArray attrs,
1260 jintArray outValues,
1261 jintArray outIndices)
1262{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001263 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001264 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001265 return JNI_FALSE;
1266 }
1267 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001268 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001269 return JNI_FALSE;
1270 }
1271 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001272 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 return JNI_FALSE;
1274 }
1275
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001276 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001277 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1278 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1279 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001280 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001281
Ashok Bhat896043d2014-01-17 16:02:38 +00001282 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001284 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001285 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 Res_value value;
1287
1288 const jsize NI = env->GetArrayLength(attrs);
1289 const jsize NV = env->GetArrayLength(outValues);
1290 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001291 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 return JNI_FALSE;
1293 }
1294
1295 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1296 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 return JNI_FALSE;
1298 }
1299
1300 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1301 jint* dest = baseDest;
1302 if (dest == NULL) {
1303 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 return JNI_FALSE;
1305 }
1306
1307 jint* indices = NULL;
1308 int indicesIdx = 0;
1309 if (outIndices != NULL) {
1310 if (env->GetArrayLength(outIndices) > NI) {
1311 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1312 }
1313 }
1314
1315 // Load default style from attribute, if specified...
1316 uint32_t defStyleBagTypeSetFlags = 0;
1317 if (defStyleAttr != 0) {
1318 Res_value value;
1319 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1320 if (value.dataType == Res_value::TYPE_REFERENCE) {
1321 defStyleRes = value.data;
1322 }
1323 }
1324 }
1325
1326 // Retrieve the style class associated with the current XML tag.
1327 int style = 0;
1328 uint32_t styleBagTypeSetFlags = 0;
1329 if (xmlParser != NULL) {
1330 ssize_t idx = xmlParser->indexOfStyle();
1331 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1332 if (value.dataType == value.TYPE_ATTRIBUTE) {
1333 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1334 value.dataType = Res_value::TYPE_NULL;
1335 }
1336 }
1337 if (value.dataType == value.TYPE_REFERENCE) {
1338 style = value.data;
1339 }
1340 }
1341 }
1342
1343 // Now lock down the resource object and start pulling stuff from it.
1344 res.lock();
1345
1346 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001347 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 uint32_t defStyleTypeSetFlags = 0;
1349 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001350 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001352 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1353 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354
1355 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001356 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001358 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001360 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1361 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
1363 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001365 XmlAttributeFinder xmlAttrFinder(xmlParser);
1366 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367
1368 // Now iterate through all of the attributes that the client has requested,
1369 // filling in each with whatever data we can find.
1370 ssize_t block = 0;
1371 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001372 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 const uint32_t curIdent = (uint32_t)src[ii];
1374
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001375 if (kDebugStyles) {
1376 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1377 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 // Try to find a value for this attribute... we prioritize values
1380 // coming from, first XML attributes, then XML style, then default
1381 // style, and finally the theme.
1382 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001383 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001385 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001387 // Walk through the xml attributes looking for the requested attribute.
1388 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1389 if (xmlAttrIdx != xmlAttrEnd) {
1390 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001392 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001393 if (kDebugStyles) {
1394 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 }
1397
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001398 if (value.dataType == Res_value::TYPE_NULL) {
1399 // Walk through the style class values looking for the requested attribute.
1400 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1401 if (styleAttrEntry != styleAttrEnd) {
1402 // We found the attribute we were looking for.
1403 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001405 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001406 if (kDebugStyles) {
1407 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1408 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 }
1411
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001412 if (value.dataType == Res_value::TYPE_NULL) {
1413 // Walk through the default style values looking for the requested attribute.
1414 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1415 if (defStyleAttrEntry != defStyleAttrEnd) {
1416 // We found the attribute we were looking for.
1417 block = defStyleAttrEntry->stringBlock;
1418 typeSetFlags = styleTypeSetFlags;
1419 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001420 if (kDebugStyles) {
1421 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 }
1425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 uint32_t resid = 0;
1427 if (value.dataType != Res_value::TYPE_NULL) {
1428 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001429 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1430 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001431 if (newBlock >= 0) {
1432 block = newBlock;
1433 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001434
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001435 if (kDebugStyles) {
1436 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 } else {
1439 // If we still don't have a value for this attribute, try to find
1440 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1442 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001443 if (kDebugStyles) {
1444 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1445 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001446 newBlock = res.resolveReference(&value, block, &resid,
1447 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001448 if (kThrowOnBadId) {
1449 if (newBlock == BAD_INDEX) {
1450 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1451 return JNI_FALSE;
1452 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001453 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001454
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001455 if (newBlock >= 0) {
1456 block = newBlock;
1457 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001458
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001459 if (kDebugStyles) {
1460 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1461 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 }
1463 }
1464
1465 // Deal with the special @null value -- it turns back to TYPE_NULL.
1466 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001467 if (kDebugStyles) {
1468 ALOGI("-> Setting to @null!");
1469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001471 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001472 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 }
1474
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001475 if (kDebugStyles) {
1476 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1477 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478
1479 // Write the final value back to Java.
1480 dest[STYLE_TYPE] = value.dataType;
1481 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001482 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1483 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 dest[STYLE_RESOURCE_ID] = resid;
1485 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001486 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1489 indicesIdx++;
1490 indices[indicesIdx] = ii;
1491 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 dest += STYLE_NUM_ENTRIES;
1494 }
1495
1496 res.unlock();
1497
1498 if (indices != NULL) {
1499 indices[0] = indicesIdx;
1500 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1501 }
1502 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1503 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1504
1505 return JNI_TRUE;
1506}
1507
1508static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001509 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 jintArray attrs,
1511 jintArray outValues,
1512 jintArray outIndices)
1513{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001514 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001515 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001516 return JNI_FALSE;
1517 }
1518 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001519 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001520 return JNI_FALSE;
1521 }
1522 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001523 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 return JNI_FALSE;
1525 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 AssetManager* am = assetManagerForJavaObject(env, clazz);
1528 if (am == NULL) {
1529 return JNI_FALSE;
1530 }
1531 const ResTable& res(am->getResources());
1532 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001533 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 const jsize NI = env->GetArrayLength(attrs);
1537 const jsize NV = env->GetArrayLength(outValues);
1538 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001539 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 return JNI_FALSE;
1541 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1544 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 return JNI_FALSE;
1546 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1549 jint* dest = baseDest;
1550 if (dest == NULL) {
1551 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001552 return JNI_FALSE;
1553 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 jint* indices = NULL;
1556 int indicesIdx = 0;
1557 if (outIndices != NULL) {
1558 if (env->GetArrayLength(outIndices) > NI) {
1559 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1560 }
1561 }
1562
1563 // Now lock down the resource object and start pulling stuff from it.
1564 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 // Retrieve the XML attributes, if requested.
1567 const jsize NX = xmlParser->getAttributeCount();
1568 jsize ix=0;
1569 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001571 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 // Now iterate through all of the attributes that the client has requested,
1574 // filling in each with whatever data we can find.
1575 ssize_t block = 0;
1576 uint32_t typeSetFlags;
1577 for (jsize ii=0; ii<NI; ii++) {
1578 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 // Try to find a value for this attribute...
1581 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001582 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001584 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001587 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 ix++;
1589 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1590 }
1591 // Retrieve the current XML attribute if it matches, and step to next.
1592 if (ix < NX && curIdent == curXmlAttr) {
1593 block = kXmlBlock;
1594 xmlParser->getAttributeValue(ix, &value);
1595 ix++;
1596 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1597 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1600 uint32_t resid = 0;
1601 if (value.dataType != Res_value::TYPE_NULL) {
1602 // Take care of resolving the found resource to its final value.
1603 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001604 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1605 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001606 if (kThrowOnBadId) {
1607 if (newBlock == BAD_INDEX) {
1608 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1609 return JNI_FALSE;
1610 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 if (newBlock >= 0) block = newBlock;
1613 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 // Deal with the special @null value -- it turns back to TYPE_NULL.
1616 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1617 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001618 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 // Write the final value back to Java.
1624 dest[STYLE_TYPE] = value.dataType;
1625 dest[STYLE_DATA] = value.data;
1626 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001627 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 dest[STYLE_RESOURCE_ID] = resid;
1629 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001630 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1633 indicesIdx++;
1634 indices[indicesIdx] = ii;
1635 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 dest += STYLE_NUM_ENTRIES;
1638 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 if (indices != NULL) {
1643 indices[0] = indicesIdx;
1644 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1645 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1648 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 return JNI_TRUE;
1651}
1652
1653static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1654 jint id)
1655{
1656 AssetManager* am = assetManagerForJavaObject(env, clazz);
1657 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001658 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
1660 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 res.lock();
1663 const ResTable::bag_entry* defStyleEnt = NULL;
1664 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1665 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001666
Ashok Bhat896043d2014-01-17 16:02:38 +00001667 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668}
1669
1670static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1671 jint id,
1672 jintArray outValues)
1673{
1674 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001675 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 return JNI_FALSE;
1677 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 AssetManager* am = assetManagerForJavaObject(env, clazz);
1680 if (am == NULL) {
1681 return JNI_FALSE;
1682 }
1683 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001684 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 Res_value value;
1686 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1691 jint* dest = baseDest;
1692 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001693 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 return JNI_FALSE;
1695 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 // Now lock down the resource object and start pulling stuff from it.
1698 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 const ResTable::bag_entry* arrayEnt = NULL;
1701 uint32_t arrayTypeSetFlags = 0;
1702 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1703 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1704 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001705
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 int i = 0;
1707 uint32_t typeSetFlags;
1708 while (i < NV && arrayEnt < endArrayEnt) {
1709 block = arrayEnt->stringBlock;
1710 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001711 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 uint32_t resid = 0;
1715 if (value.dataType != Res_value::TYPE_NULL) {
1716 // Take care of resolving the found resource to its final value.
1717 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001718 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1719 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001720 if (kThrowOnBadId) {
1721 if (newBlock == BAD_INDEX) {
1722 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1723 return JNI_FALSE;
1724 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001725 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 if (newBlock >= 0) block = newBlock;
1727 }
1728
1729 // Deal with the special @null value -- it turns back to TYPE_NULL.
1730 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1731 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001732 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 }
1734
1735 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1736
1737 // Write the final value back to Java.
1738 dest[STYLE_TYPE] = value.dataType;
1739 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001740 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 dest[STYLE_RESOURCE_ID] = resid;
1742 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001743 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 dest += STYLE_NUM_ENTRIES;
1745 i+= STYLE_NUM_ENTRIES;
1746 arrayEnt++;
1747 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 return i;
1756}
1757
Ashok Bhat896043d2014-01-17 16:02:38 +00001758static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 jint cookie,
1760 jstring fileName)
1761{
1762 AssetManager* am = assetManagerForJavaObject(env, clazz);
1763 if (am == NULL) {
1764 return 0;
1765 }
1766
Steve Block71f2cf12011-10-20 11:56:00 +01001767 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768
Elliott Hughes69a017b2011-04-08 14:10:28 -07001769 ScopedUtfChars fileName8(env, fileName);
1770 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 return 0;
1772 }
1773
Adam Lesinskide898ff2014-01-29 18:20:45 -08001774 int32_t assetCookie = static_cast<int32_t>(cookie);
1775 Asset* a = assetCookie
1776 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1777 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778
1779 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001780 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 return 0;
1782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783
Adam Lesinskide898ff2014-01-29 18:20:45 -08001784 const DynamicRefTable* dynamicRefTable =
1785 am->getResources().getDynamicRefTableForCookie(assetCookie);
1786 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1788 a->close();
1789 delete a;
1790
1791 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001792 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 return 0;
1794 }
1795
Ashok Bhat896043d2014-01-17 16:02:38 +00001796 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797}
1798
1799static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1800 jint arrayResId)
1801{
1802 AssetManager* am = assetManagerForJavaObject(env, clazz);
1803 if (am == NULL) {
1804 return NULL;
1805 }
1806 const ResTable& res(am->getResources());
1807
1808 const ResTable::bag_entry* startOfBag;
1809 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1810 if (N < 0) {
1811 return NULL;
1812 }
1813
1814 jintArray array = env->NewIntArray(N * 2);
1815 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 res.unlockBag(startOfBag);
1817 return NULL;
1818 }
1819
1820 Res_value value;
1821 const ResTable::bag_entry* bag = startOfBag;
1822 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1823 jint stringIndex = -1;
1824 jint stringBlock = 0;
1825 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 // Take care of resolving the found resource to its final value.
1828 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1829 if (value.dataType == Res_value::TYPE_STRING) {
1830 stringIndex = value.data;
1831 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001832
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001833 if (kThrowOnBadId) {
1834 if (stringBlock == BAD_INDEX) {
1835 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1836 return array;
1837 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001838 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 //todo: It might be faster to allocate a C array to contain
1841 // the blocknums and indices, put them in there and then
1842 // do just one SetIntArrayRegion()
1843 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1844 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1845 j = j + 2;
1846 }
1847 res.unlockBag(startOfBag);
1848 return array;
1849}
1850
1851static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1852 jint arrayResId)
1853{
1854 AssetManager* am = assetManagerForJavaObject(env, clazz);
1855 if (am == NULL) {
1856 return NULL;
1857 }
1858 const ResTable& res(am->getResources());
1859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 const ResTable::bag_entry* startOfBag;
1861 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1862 if (N < 0) {
1863 return NULL;
1864 }
1865
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001866 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001867 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 res.unlockBag(startOfBag);
1869 return NULL;
1870 }
1871
1872 Res_value value;
1873 const ResTable::bag_entry* bag = startOfBag;
1874 size_t strLen = 0;
1875 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1876 value = bag->map.value;
1877 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 // Take care of resolving the found resource to its final value.
1880 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001881 if (kThrowOnBadId) {
1882 if (block == BAD_INDEX) {
1883 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1884 return array;
1885 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001888 const ResStringPool* pool = res.getTableStringBlock(block);
1889 const char* str8 = pool->string8At(value.data, &strLen);
1890 if (str8 != NULL) {
1891 str = env->NewStringUTF(str8);
1892 } else {
1893 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001894 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1895 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001896 }
1897
1898 // If one of our NewString{UTF} calls failed due to memory, an
1899 // exception will be pending.
1900 if (env->ExceptionCheck()) {
1901 res.unlockBag(startOfBag);
1902 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 }
Kenny Root780d2a12010-02-22 22:36:26 -08001904
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001905 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001906
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001907 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1908 // If we have a large amount of strings in our array, we might
1909 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001910 env->DeleteLocalRef(str);
1911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
1913 res.unlockBag(startOfBag);
1914 return array;
1915}
1916
1917static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1918 jint arrayResId)
1919{
1920 AssetManager* am = assetManagerForJavaObject(env, clazz);
1921 if (am == NULL) {
1922 return NULL;
1923 }
1924 const ResTable& res(am->getResources());
1925
1926 const ResTable::bag_entry* startOfBag;
1927 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1928 if (N < 0) {
1929 return NULL;
1930 }
1931
1932 jintArray array = env->NewIntArray(N);
1933 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 res.unlockBag(startOfBag);
1935 return NULL;
1936 }
1937
1938 Res_value value;
1939 const ResTable::bag_entry* bag = startOfBag;
1940 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1941 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 // Take care of resolving the found resource to its final value.
1944 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001945 if (kThrowOnBadId) {
1946 if (block == BAD_INDEX) {
1947 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1948 return array;
1949 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 if (value.dataType >= Res_value::TYPE_FIRST_INT
1952 && value.dataType <= Res_value::TYPE_LAST_INT) {
1953 int intVal = value.data;
1954 env->SetIntArrayRegion(array, i, 1, &intVal);
1955 }
1956 }
1957 res.unlockBag(startOfBag);
1958 return array;
1959}
1960
Jon Miranda042ad632014-09-03 17:57:35 -07001961static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1962 jint styleId)
1963{
1964 AssetManager* am = assetManagerForJavaObject(env, clazz);
1965 if (am == NULL) {
1966 return NULL;
1967 }
1968 const ResTable& res(am->getResources());
1969
1970 const ResTable::bag_entry* startOfBag;
1971 const ssize_t N = res.lockBag(styleId, &startOfBag);
1972 if (N < 0) {
1973 return NULL;
1974 }
1975
1976 jintArray array = env->NewIntArray(N);
1977 if (array == NULL) {
1978 res.unlockBag(startOfBag);
1979 return NULL;
1980 }
1981
Jon Miranda042ad632014-09-03 17:57:35 -07001982 const ResTable::bag_entry* bag = startOfBag;
1983 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1984 int resourceId = bag->map.name.ident;
1985 env->SetIntArrayRegion(array, i, 1, &resourceId);
1986 }
1987 res.unlockBag(startOfBag);
1988 return array;
1989}
1990
Mårten Kongstad48d22322014-01-31 14:43:27 +01001991static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001993 if (isSystem) {
1994 verifySystemIdmaps();
1995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 AssetManager* am = new AssetManager();
1997 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001998 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 return;
2000 }
2001
2002 am->addDefaultAssets();
2003
Steve Block71f2cf12011-10-20 11:56:00 +01002004 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002005 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006}
2007
2008static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2009{
2010 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002011 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002012 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 if (am != NULL) {
2014 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002015 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 }
2017}
2018
2019static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2020{
2021 return Asset::getGlobalCount();
2022}
2023
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002024static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2025{
2026 String8 alloc = Asset::getAssetAllocations();
2027 if (alloc.length() <= 0) {
2028 return NULL;
2029 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002030
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002031 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002032 return str;
2033}
2034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2036{
2037 return AssetManager::getGlobalCount();
2038}
2039
2040// ----------------------------------------------------------------------------
2041
2042/*
2043 * JNI registration.
2044 */
2045static JNINativeMethod gAssetManagerMethods[] = {
2046 /* name, signature, funcPtr */
2047
2048 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002049 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 (void*) android_content_AssetManager_openAsset },
2051 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2052 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002053 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 (void*) android_content_AssetManager_openNonAssetNative },
2055 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2056 (void*) android_content_AssetManager_openNonAssetFdNative },
2057 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2058 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002059 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002061 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002063 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002065 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002067 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002069 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002071 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002073 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002074 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 { "isUpToDate", "()Z",
2076 (void*) android_content_AssetManager_isUpToDate },
2077
2078 // Resources.
2079 { "setLocale", "(Ljava/lang/String;)V",
2080 (void*) android_content_AssetManager_setLocale },
2081 { "getLocales", "()[Ljava/lang/String;",
2082 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002083 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 (void*) android_content_AssetManager_setConfiguration },
2085 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2086 (void*) android_content_AssetManager_getResourceIdentifier },
2087 { "getResourceName","(I)Ljava/lang/String;",
2088 (void*) android_content_AssetManager_getResourceName },
2089 { "getResourcePackageName","(I)Ljava/lang/String;",
2090 (void*) android_content_AssetManager_getResourcePackageName },
2091 { "getResourceTypeName","(I)Ljava/lang/String;",
2092 (void*) android_content_AssetManager_getResourceTypeName },
2093 { "getResourceEntryName","(I)Ljava/lang/String;",
2094 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002095 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 (void*) android_content_AssetManager_loadResourceValue },
2097 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2098 (void*) android_content_AssetManager_loadResourceBagValue },
2099 { "getStringBlockCount","()I",
2100 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002101 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 (void*) android_content_AssetManager_getNativeStringBlock },
2103 { "getCookieName","(I)Ljava/lang/String;",
2104 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002105 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2106 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107
2108 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002109 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002111 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002113 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002115 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002117 { "clearTheme", "(J)V",
2118 (void*) android_content_AssetManager_clearTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002119 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 (void*) android_content_AssetManager_loadThemeAttributeValue },
Alan Viverettec1d52792015-05-05 09:49:03 -07002121 { "getThemeChangingConfigurations", "(J)I",
2122 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002123 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002125 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002127 { "resolveAttrs","(JII[I[I[I[I)Z",
2128 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002129 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 (void*) android_content_AssetManager_retrieveAttributes },
2131 { "getArraySize","(I)I",
2132 (void*) android_content_AssetManager_getArraySize },
2133 { "retrieveArray","(I[I)I",
2134 (void*) android_content_AssetManager_retrieveArray },
2135
2136 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002137 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 (void*) android_content_AssetManager_openXmlAssetNative },
2139
2140 // Arrays.
2141 { "getArrayStringResource","(I)[Ljava/lang/String;",
2142 (void*) android_content_AssetManager_getArrayStringResource },
2143 { "getArrayStringInfo","(I)[I",
2144 (void*) android_content_AssetManager_getArrayStringInfo },
2145 { "getArrayIntResource","(I)[I",
2146 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002147 { "getStyleAttributes","(I)[I",
2148 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149
2150 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002151 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 (void*) android_content_AssetManager_init },
2153 { "destroy", "()V",
2154 (void*) android_content_AssetManager_destroy },
2155 { "getGlobalAssetCount", "()I",
2156 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002157 { "getAssetAllocations", "()Ljava/lang/String;",
2158 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002160 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161};
2162
2163int register_android_content_AssetManager(JNIEnv* env)
2164{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002165 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2166 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2167 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2168 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2169 "Ljava/lang/CharSequence;");
2170 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2171 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2172 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2173 "changingConfigurations", "I");
2174 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175
Andreas Gampe987f79f2014-11-18 17:29:46 -08002176 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2177 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2178 "Landroid/os/ParcelFileDescriptor;");
2179 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2180 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181
Andreas Gampe987f79f2014-11-18 17:29:46 -08002182 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2183 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184
Andreas Gampe987f79f2014-11-18 17:29:46 -08002185 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2186 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187
Andreas Gampe987f79f2014-11-18 17:29:46 -08002188 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2189 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2190 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2191 "<init>", "()V");
2192 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2193 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002194
Andreas Gampe987f79f2014-11-18 17:29:46 -08002195 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2196 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197}
2198
2199}; // namespace android