blob: 9aa544fb4e9d2c07e6a2bb0c6cdd0ec0414000ce [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
Filip Gruszczynski23493322015-07-29 17:02:59 -070085static struct configuration_offsets_t
86{
87 jclass classObject;
88 jmethodID constructor;
89 jfieldID mSmallestScreenWidthDpOffset;
90 jfieldID mScreenWidthDpOffset;
91 jfieldID mScreenHeightDpOffset;
92} gConfigurationOffsets;
93
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094jclass g_stringClass = NULL;
95
96// ----------------------------------------------------------------------------
97
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070099 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 STYLE_TYPE = 0,
101 STYLE_DATA = 1,
102 STYLE_ASSET_COOKIE = 2,
103 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700104 STYLE_CHANGING_CONFIGURATIONS = 4,
105 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106};
107
108static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
109 const Res_value& value, uint32_t ref, ssize_t block,
110 uint32_t typeSpecFlags, ResTable_config* config = NULL);
111
112jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
113 const Res_value& value, uint32_t ref, ssize_t block,
114 uint32_t typeSpecFlags, ResTable_config* config)
115{
116 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
117 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000118 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
120 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
121 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
122 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
123 typeSpecFlags);
124 if (config != NULL) {
125 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
126 }
127 return block;
128}
129
Mårten Kongstad48d22322014-01-31 14:43:27 +0100130// This is called by zygote (running as user root) as part of preloadResources.
131static void verifySystemIdmaps()
132{
133 pid_t pid;
134 char system_id[10];
135
136 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
137
138 switch (pid = fork()) {
139 case -1:
140 ALOGE("failed to fork for idmap: %s", strerror(errno));
141 break;
142 case 0: // child
143 {
144 struct __user_cap_header_struct capheader;
145 struct __user_cap_data_struct capdata;
146
147 memset(&capheader, 0, sizeof(capheader));
148 memset(&capdata, 0, sizeof(capdata));
149
150 capheader.version = _LINUX_CAPABILITY_VERSION;
151 capheader.pid = 0;
152
153 if (capget(&capheader, &capdata) != 0) {
154 ALOGE("capget: %s\n", strerror(errno));
155 exit(1);
156 }
157
158 capdata.effective = capdata.permitted;
159 if (capset(&capheader, &capdata) != 0) {
160 ALOGE("capset: %s\n", strerror(errno));
161 exit(1);
162 }
163
164 if (setgid(AID_SYSTEM) != 0) {
165 ALOGE("setgid: %s\n", strerror(errno));
166 exit(1);
167 }
168
169 if (setuid(AID_SYSTEM) != 0) {
170 ALOGE("setuid: %s\n", strerror(errno));
171 exit(1);
172 }
173
174 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
175 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
176 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
177 ALOGE("failed to execl for idmap: %s", strerror(errno));
178 exit(1); // should never get here
179 }
180 break;
181 default: // parent
182 waitpid(pid, NULL, 0);
183 break;
184 }
185}
186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187// ----------------------------------------------------------------------------
188
189// this guy is exported to other jni routines
190AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
191{
Ashok Bhat896043d2014-01-17 16:02:38 +0000192 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
193 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 if (am != NULL) {
195 return am;
196 }
197 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
198 return NULL;
199}
200
Ashok Bhat896043d2014-01-17 16:02:38 +0000201static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 jstring fileName, jint mode)
203{
204 AssetManager* am = assetManagerForJavaObject(env, clazz);
205 if (am == NULL) {
206 return 0;
207 }
208
Steve Block71f2cf12011-10-20 11:56:00 +0100209 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210
Elliott Hughes69a017b2011-04-08 14:10:28 -0700211 ScopedUtfChars fileName8(env, fileName);
212 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000213 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 return -1;
215 }
216
217 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
218 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700219 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 return -1;
221 }
222
Elliott Hughes69a017b2011-04-08 14:10:28 -0700223 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224
225 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700226 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 return -1;
228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
230 //printf("Created Asset Stream: %p\n", a);
231
Ashok Bhat896043d2014-01-17 16:02:38 +0000232 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233}
234
235static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
236{
Kenny Rootddb76c42010-11-24 12:56:06 -0800237 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 int fd = a->openFileDescriptor(&startOffset, &length);
239 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700242 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 "This file can not be opened as a file descriptor; it is probably compressed");
244 return NULL;
245 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
248 if (offsets == NULL) {
249 close(fd);
250 return NULL;
251 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 offsets[0] = startOffset;
254 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700257
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700258 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 if (fileDesc == NULL) {
260 close(fd);
261 return NULL;
262 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 return newParcelFileDescriptor(env, fileDesc);
265}
266
267static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
268 jstring fileName, jlongArray outOffsets)
269{
270 AssetManager* am = assetManagerForJavaObject(env, clazz);
271 if (am == NULL) {
272 return NULL;
273 }
274
Steve Block71f2cf12011-10-20 11:56:00 +0100275 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276
Elliott Hughes69a017b2011-04-08 14:10:28 -0700277 ScopedUtfChars fileName8(env, fileName);
278 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 return NULL;
280 }
281
Elliott Hughes69a017b2011-04-08 14:10:28 -0700282 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283
284 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700285 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 return NULL;
287 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288
289 //printf("Created Asset Stream: %p\n", a);
290
291 return returnParcelFileDescriptor(env, a, outOffsets);
292}
293
Ashok Bhat896043d2014-01-17 16:02:38 +0000294static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 jint cookie,
296 jstring fileName,
297 jint mode)
298{
299 AssetManager* am = assetManagerForJavaObject(env, clazz);
300 if (am == NULL) {
301 return 0;
302 }
303
Steve Block71f2cf12011-10-20 11:56:00 +0100304 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
Elliott Hughes69a017b2011-04-08 14:10:28 -0700306 ScopedUtfChars fileName8(env, fileName);
307 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 return -1;
309 }
310
311 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
312 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700313 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 return -1;
315 }
316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000318 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
319 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700320 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
322 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700323 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324 return -1;
325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326
327 //printf("Created Asset Stream: %p\n", a);
328
Ashok Bhat896043d2014-01-17 16:02:38 +0000329 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330}
331
332static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
333 jint cookie,
334 jstring fileName,
335 jlongArray outOffsets)
336{
337 AssetManager* am = assetManagerForJavaObject(env, clazz);
338 if (am == NULL) {
339 return NULL;
340 }
341
Steve Block71f2cf12011-10-20 11:56:00 +0100342 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
Elliott Hughes69a017b2011-04-08 14:10:28 -0700344 ScopedUtfChars fileName8(env, fileName);
345 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return NULL;
347 }
348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000350 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700351 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352
353 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700354 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 return NULL;
356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357
358 //printf("Created Asset Stream: %p\n", a);
359
360 return returnParcelFileDescriptor(env, a, outOffsets);
361}
362
363static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
364 jstring fileName)
365{
366 AssetManager* am = assetManagerForJavaObject(env, clazz);
367 if (am == NULL) {
368 return NULL;
369 }
370
Elliott Hughes69a017b2011-04-08 14:10:28 -0700371 ScopedUtfChars fileName8(env, fileName);
372 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 return NULL;
374 }
375
Elliott Hughes69a017b2011-04-08 14:10:28 -0700376 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377
378 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700379 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 return NULL;
381 }
382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 size_t N = dir->getFileCount();
384
385 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100386 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 delete dir;
389 return NULL;
390 }
391
392 for (size_t i=0; i<N; i++) {
393 const String8& name = dir->getFileName(i);
394 jstring str = env->NewStringUTF(name.string());
395 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 delete dir;
397 return NULL;
398 }
399 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700400 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 }
402
403 delete dir;
404
405 return array;
406}
407
408static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000409 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410{
Ashok Bhat896043d2014-01-17 16:02:38 +0000411 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412
413 //printf("Destroying Asset Stream: %p\n", a);
414
415 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700416 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 return;
418 }
419
420 delete a;
421}
422
423static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000424 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425{
Ashok Bhat896043d2014-01-17 16:02:38 +0000426 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427
428 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700429 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 return -1;
431 }
432
433 uint8_t b;
434 ssize_t res = a->read(&b, 1);
435 return res == 1 ? b : -1;
436}
437
438static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000439 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 jint off, jint len)
441{
Ashok Bhat896043d2014-01-17 16:02:38 +0000442 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443
444 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700445 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 return -1;
447 }
448
449 if (len == 0) {
450 return 0;
451 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 jsize bLen = env->GetArrayLength(bArray);
454 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700455 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 return -1;
457 }
458
459 jbyte* b = env->GetByteArrayElements(bArray, NULL);
460 ssize_t res = a->read(b+off, len);
461 env->ReleaseByteArrayElements(bArray, b, 0);
462
Ashok Bhat896043d2014-01-17 16:02:38 +0000463 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464
465 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700466 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 }
468 return -1;
469}
470
471static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000472 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 jlong offset, jint whence)
474{
Ashok Bhat896043d2014-01-17 16:02:38 +0000475 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476
477 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700478 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 return -1;
480 }
481
482 return a->seek(
483 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
484}
485
486static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000487 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488{
Ashok Bhat896043d2014-01-17 16:02:38 +0000489 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490
491 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700492 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 return -1;
494 }
495
496 return a->getLength();
497}
498
499static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000500 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501{
Ashok Bhat896043d2014-01-17 16:02:38 +0000502 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503
504 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700505 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 return -1;
507 }
508
509 return a->getRemainingLength();
510}
511
512static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
513 jstring path)
514{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700515 ScopedUtfChars path8(env, path);
516 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800517 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 }
519
520 AssetManager* am = assetManagerForJavaObject(env, clazz);
521 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800522 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 }
524
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000525 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700526 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000528 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529}
530
Mårten Kongstad48d22322014-01-31 14:43:27 +0100531static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
532 jstring idmapPath)
533{
534 ScopedUtfChars idmapPath8(env, idmapPath);
535 if (idmapPath8.c_str() == NULL) {
536 return 0;
537 }
538
539 AssetManager* am = assetManagerForJavaObject(env, clazz);
540 if (am == NULL) {
541 return 0;
542 }
543
544 int32_t cookie;
545 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
546
547 return (res) ? (jint)cookie : 0;
548}
549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
551{
552 AssetManager* am = assetManagerForJavaObject(env, clazz);
553 if (am == NULL) {
554 return JNI_TRUE;
555 }
556 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
557}
558
559static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
560 jstring locale)
561{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700562 ScopedUtfChars locale8(env, locale);
563 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 return;
565 }
566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 AssetManager* am = assetManagerForJavaObject(env, clazz);
568 if (am == NULL) {
569 return;
570 }
571
Elliott Hughes69a017b2011-04-08 14:10:28 -0700572 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573}
574
575static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
576{
577 Vector<String8> locales;
578
579 AssetManager* am = assetManagerForJavaObject(env, clazz);
580 if (am == NULL) {
581 return NULL;
582 }
583
584 am->getLocales(&locales);
585
586 const int N = locales.size();
587
588 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
589 if (result == NULL) {
590 return NULL;
591 }
592
593 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700594 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700595 if (str == NULL) {
596 return NULL;
597 }
598 env->SetObjectArrayElement(result, i, str);
599 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 }
601
602 return result;
603}
604
Filip Gruszczynski23493322015-07-29 17:02:59 -0700605static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
606 jobject result = env->NewObject(gConfigurationOffsets.classObject,
607 gConfigurationOffsets.constructor);
608 if (result == NULL) {
609 return NULL;
610 }
611
612 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
613 config.smallestScreenWidthDp);
614 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
615 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
616
617 return result;
618}
619
620static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
621 const Vector<ResTable_config>& configs) {
622 const int N = configs.size();
623 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
624 if (result == NULL) {
625 return NULL;
626 }
627
628 for (int i=0; i<N; i++) {
629 jobject config = constructConfigurationObject(env, configs[i]);
630 if (config == NULL) {
631 env->DeleteLocalRef(result);
632 return NULL;
633 }
634
635 env->SetObjectArrayElement(result, i, config);
636 env->DeleteLocalRef(config);
637 }
638
639 return result;
640}
641
642static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
643 AssetManager* am = assetManagerForJavaObject(env, clazz);
644 if (am == NULL) {
645 return NULL;
646 }
647
648 const ResTable& res(am->getResources());
649 Vector<ResTable_config> configs;
650 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
651
652 return getSizeConfigurationsInternal(env, configs);
653}
654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
656 jint mcc, jint mnc,
657 jstring locale, jint orientation,
658 jint touchscreen, jint density,
659 jint keyboard, jint keyboardHidden,
660 jint navigation,
661 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700662 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700663 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100664 jint screenLayout, jint uiMode,
665 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666{
667 AssetManager* am = assetManagerForJavaObject(env, clazz);
668 if (am == NULL) {
669 return;
670 }
671
672 ResTable_config config;
673 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700676
Adam Lesinski2738c962015-05-14 14:25:36 -0700677 // Constants duplicated from Java class android.content.res.Configuration.
678 static const jint kScreenLayoutRoundMask = 0x300;
679 static const jint kScreenLayoutRoundShift = 8;
680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 config.mcc = (uint16_t)mcc;
682 config.mnc = (uint16_t)mnc;
683 config.orientation = (uint8_t)orientation;
684 config.touchscreen = (uint8_t)touchscreen;
685 config.density = (uint16_t)density;
686 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700687 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 config.navigation = (uint8_t)navigation;
689 config.screenWidth = (uint16_t)screenWidth;
690 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700691 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700692 config.screenWidthDp = (uint16_t)screenWidthDp;
693 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700694 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100695 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 config.sdkVersion = (uint16_t)sdkVersion;
697 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700698
699 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
700 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
701 // into screenLayout2.
702 config.screenLayout2 =
703 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
708}
709
710static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
711 jstring name,
712 jstring defType,
713 jstring defPackage)
714{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700715 ScopedStringChars name16(env, name);
716 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 return 0;
718 }
719
720 AssetManager* am = assetManagerForJavaObject(env, clazz);
721 if (am == NULL) {
722 return 0;
723 }
724
Dan Albert66987492014-11-20 11:41:21 -0800725 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
726 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
727 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 jsize defTypeLen = defType
729 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800730 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
731 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
732 NULL))
733 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 jsize defPackageLen = defPackage
735 ? env->GetStringLength(defPackage) : 0;
736
737 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800738 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
739 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740
741 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800742 env->ReleaseStringChars(defPackage,
743 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 }
745 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800746 env->ReleaseStringChars(defType,
747 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749
750 return ident;
751}
752
753static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
754 jint resid)
755{
756 AssetManager* am = assetManagerForJavaObject(env, clazz);
757 if (am == NULL) {
758 return NULL;
759 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700762 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 return NULL;
764 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 String16 str;
767 if (name.package != NULL) {
768 str.setTo(name.package, name.packageLen);
769 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700770 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 if (str.size() > 0) {
772 char16_t div = ':';
773 str.append(&div, 1);
774 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700775 if (name.type8 != NULL) {
776 str.append(String16(name.type8, name.typeLen));
777 } else {
778 str.append(name.type, name.typeLen);
779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700781 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 if (str.size() > 0) {
783 char16_t div = '/';
784 str.append(&div, 1);
785 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700786 if (name.name8 != NULL) {
787 str.append(String16(name.name8, name.nameLen));
788 } else {
789 str.append(name.name, name.nameLen);
790 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 return env->NewString((const jchar*)str.string(), str.size());
794}
795
796static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
797 jint resid)
798{
799 AssetManager* am = assetManagerForJavaObject(env, clazz);
800 if (am == NULL) {
801 return NULL;
802 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700805 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 return NULL;
807 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 if (name.package != NULL) {
810 return env->NewString((const jchar*)name.package, name.packageLen);
811 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 return NULL;
814}
815
816static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
817 jint resid)
818{
819 AssetManager* am = assetManagerForJavaObject(env, clazz);
820 if (am == NULL) {
821 return NULL;
822 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700825 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 return NULL;
827 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700828
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700829 if (name.type8 != NULL) {
830 return env->NewStringUTF(name.type8);
831 }
832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 if (name.type != NULL) {
834 return env->NewString((const jchar*)name.type, name.typeLen);
835 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 return NULL;
838}
839
840static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
841 jint resid)
842{
843 AssetManager* am = assetManagerForJavaObject(env, clazz);
844 if (am == NULL) {
845 return NULL;
846 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700849 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 return NULL;
851 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700852
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700853 if (name.name8 != NULL) {
854 return env->NewStringUTF(name.name8);
855 }
856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800857 if (name.name != NULL) {
858 return env->NewString((const jchar*)name.name, name.nameLen);
859 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 return NULL;
862}
863
864static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
865 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700866 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 jobject outValue,
868 jboolean resolve)
869{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800870 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800871 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700872 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 AssetManager* am = assetManagerForJavaObject(env, clazz);
875 if (am == NULL) {
876 return 0;
877 }
878 const ResTable& res(am->getResources());
879
880 Res_value value;
881 ResTable_config config;
882 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700883 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800884 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800885 if (block == BAD_INDEX) {
886 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
887 return 0;
888 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800889 }
890 uint32_t ref = ident;
891 if (resolve) {
892 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
893 if (kThrowOnBadId) {
894 if (block == BAD_INDEX) {
895 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
896 return 0;
897 }
898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000900 if (block >= 0) {
901 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
902 }
903
904 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905}
906
907static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
908 jint ident, jint bagEntryId,
909 jobject outValue, jboolean resolve)
910{
911 AssetManager* am = assetManagerForJavaObject(env, clazz);
912 if (am == NULL) {
913 return 0;
914 }
915 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 // Now lock down the resource object and start pulling stuff from it.
918 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800920 ssize_t block = -1;
921 Res_value value;
922
923 const ResTable::bag_entry* entry = NULL;
924 uint32_t typeSpecFlags;
925 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
926
927 for (ssize_t i=0; i<entryCount; i++) {
928 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
929 block = entry->stringBlock;
930 value = entry->map.value;
931 }
932 entry++;
933 }
934
935 res.unlock();
936
937 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000938 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800939 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 uint32_t ref = ident;
942 if (resolve) {
943 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800944 if (kThrowOnBadId) {
945 if (block == BAD_INDEX) {
946 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
947 return 0;
948 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000951 if (block >= 0) {
952 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
953 }
954
955 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956}
957
958static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
959{
960 AssetManager* am = assetManagerForJavaObject(env, clazz);
961 if (am == NULL) {
962 return 0;
963 }
964 return am->getResources().getTableCount();
965}
966
Ashok Bhat896043d2014-01-17 16:02:38 +0000967static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 jint block)
969{
970 AssetManager* am = assetManagerForJavaObject(env, clazz);
971 if (am == NULL) {
972 return 0;
973 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000974 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975}
976
977static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
978 jint cookie)
979{
980 AssetManager* am = assetManagerForJavaObject(env, clazz);
981 if (am == NULL) {
982 return NULL;
983 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000984 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700986 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 return NULL;
988 }
989 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990 return str;
991}
992
Adam Lesinskide898ff2014-01-29 18:20:45 -0800993static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
994{
995 AssetManager* am = assetManagerForJavaObject(env, clazz);
996 if (am == NULL) {
997 return 0;
998 }
999
1000 const ResTable& res = am->getResources();
1001
1002 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1003 gSparseArrayOffsets.constructor);
1004 const size_t N = res.getBasePackageCount();
1005 for (size_t i = 0; i < N; i++) {
1006 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -08001007 env->CallVoidMethod(
1008 sparseArray, gSparseArrayOffsets.put,
1009 static_cast<jint>(res.getBasePackageId(i)),
1010 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1011 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -08001012 }
1013 return sparseArray;
1014}
1015
Ashok Bhat896043d2014-01-17 16:02:38 +00001016static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017{
1018 AssetManager* am = assetManagerForJavaObject(env, clazz);
1019 if (am == NULL) {
1020 return 0;
1021 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001022 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023}
1024
1025static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001026 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027{
Ashok Bhat896043d2014-01-17 16:02:38 +00001028 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 delete theme;
1030}
1031
1032static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001033 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 jint styleRes,
1035 jboolean force)
1036{
Ashok Bhat896043d2014-01-17 16:02:38 +00001037 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 theme->applyStyle(styleRes, force ? true : false);
1039}
1040
1041static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001042 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043{
Ashok Bhat896043d2014-01-17 16:02:38 +00001044 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1045 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 dest->setTo(*src);
1047}
1048
Alan Viverettee54d2452015-05-06 10:41:43 -07001049static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1050{
1051 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1052 theme->clear();
1053}
1054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001056 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057{
Ashok Bhat896043d2014-01-17 16:02:38 +00001058 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 const ResTable& res(theme->getResTable());
1060
1061 Res_value value;
1062 // XXX value could be different in different configs!
1063 uint32_t typeSpecFlags = 0;
1064 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1065 uint32_t ref = 0;
1066 if (resolve) {
1067 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001068 if (kThrowOnBadId) {
1069 if (block == BAD_INDEX) {
1070 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1071 return 0;
1072 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001073 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 }
1075 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1076}
1077
Alan Viverettec1d52792015-05-05 09:49:03 -07001078static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1079 jlong themeHandle)
1080{
1081 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1082 return theme->getChangingConfigurations();
1083}
1084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001086 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 jstring tag, jstring prefix)
1088{
Ashok Bhat896043d2014-01-17 16:02:38 +00001089 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001091 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 // XXX Need to use params.
1094 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095}
1096
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001097class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1098public:
1099 XmlAttributeFinder(const ResXMLParser* parser)
1100 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1101 , mParser(parser) {}
1102
1103 inline uint32_t getAttribute(jsize index) const {
1104 return mParser->getAttributeNameResID(index);
1105 }
1106
1107private:
1108 const ResXMLParser* mParser;
1109};
1110
1111class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1112public:
1113 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1114 : BackTrackingAttributeFinder(start, end) {}
1115
1116 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1117 return entry->map.name.ident;
1118 }
1119};
1120
Alan Viverette52b999f2014-03-24 18:00:26 -07001121static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1122 jlong themeToken,
1123 jint defStyleAttr,
1124 jint defStyleRes,
1125 jintArray inValues,
1126 jintArray attrs,
1127 jintArray outValues,
1128 jintArray outIndices)
1129{
1130 if (themeToken == 0) {
1131 jniThrowNullPointerException(env, "theme token");
1132 return JNI_FALSE;
1133 }
1134 if (attrs == NULL) {
1135 jniThrowNullPointerException(env, "attrs");
1136 return JNI_FALSE;
1137 }
1138 if (outValues == NULL) {
1139 jniThrowNullPointerException(env, "out values");
1140 return JNI_FALSE;
1141 }
1142
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001143 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001144 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1145 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001146 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001147
1148 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1149 const ResTable& res = theme->getResTable();
1150 ResTable_config config;
1151 Res_value value;
1152
1153 const jsize NI = env->GetArrayLength(attrs);
1154 const jsize NV = env->GetArrayLength(outValues);
1155 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1156 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1157 return JNI_FALSE;
1158 }
1159
1160 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1161 if (src == NULL) {
1162 return JNI_FALSE;
1163 }
1164
1165 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1166 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1167
1168 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1169 jint* dest = baseDest;
1170 if (dest == NULL) {
1171 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1172 return JNI_FALSE;
1173 }
1174
1175 jint* indices = NULL;
1176 int indicesIdx = 0;
1177 if (outIndices != NULL) {
1178 if (env->GetArrayLength(outIndices) > NI) {
1179 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1180 }
1181 }
1182
1183 // Load default style from attribute, if specified...
1184 uint32_t defStyleBagTypeSetFlags = 0;
1185 if (defStyleAttr != 0) {
1186 Res_value value;
1187 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1188 if (value.dataType == Res_value::TYPE_REFERENCE) {
1189 defStyleRes = value.data;
1190 }
1191 }
1192 }
1193
1194 // Now lock down the resource object and start pulling stuff from it.
1195 res.lock();
1196
1197 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001198 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001199 uint32_t defStyleTypeSetFlags = 0;
1200 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001201 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001202 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001203 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1204 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001205
1206 // Now iterate through all of the attributes that the client has requested,
1207 // filling in each with whatever data we can find.
1208 ssize_t block = 0;
1209 uint32_t typeSetFlags;
1210 for (jsize ii=0; ii<NI; ii++) {
1211 const uint32_t curIdent = (uint32_t)src[ii];
1212
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001213 if (kDebugStyles) {
1214 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1215 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001216
1217 // Try to find a value for this attribute... we prioritize values
1218 // coming from, first XML attributes, then XML style, then default
1219 // style, and finally the theme.
1220 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001221 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001222 typeSetFlags = 0;
1223 config.density = 0;
1224
1225 // Retrieve the current input value if available.
1226 if (NSV > 0 && srcValues[ii] != 0) {
1227 block = -1;
1228 value.dataType = Res_value::TYPE_ATTRIBUTE;
1229 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001230 if (kDebugStyles) {
1231 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1232 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001233 }
1234
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001235 if (value.dataType == Res_value::TYPE_NULL) {
1236 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1237 if (defStyleEntry != defStyleEnd) {
1238 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001239 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001240 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001241 if (kDebugStyles) {
1242 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1243 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001244 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001245 }
1246
1247 uint32_t resid = 0;
1248 if (value.dataType != Res_value::TYPE_NULL) {
1249 // Take care of resolving the found resource to its final value.
1250 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1251 &resid, &typeSetFlags, &config);
1252 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001253 if (kDebugStyles) {
1254 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1255 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001256 } else {
1257 // If we still don't have a value for this attribute, try to find
1258 // it in the theme!
1259 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1260 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001261 if (kDebugStyles) {
1262 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1263 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001264 newBlock = res.resolveReference(&value, block, &resid,
1265 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001266 if (kThrowOnBadId) {
1267 if (newBlock == BAD_INDEX) {
1268 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1269 return JNI_FALSE;
1270 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001271 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001272 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001273 if (kDebugStyles) {
1274 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1275 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001276 }
1277 }
1278
1279 // Deal with the special @null value -- it turns back to TYPE_NULL.
1280 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001281 if (kDebugStyles) {
1282 ALOGI("-> Setting to @null!");
1283 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001284 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001285 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001286 block = -1;
1287 }
1288
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001289 if (kDebugStyles) {
1290 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1291 value.data);
1292 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001293
1294 // Write the final value back to Java.
1295 dest[STYLE_TYPE] = value.dataType;
1296 dest[STYLE_DATA] = value.data;
1297 dest[STYLE_ASSET_COOKIE] =
1298 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1299 dest[STYLE_RESOURCE_ID] = resid;
1300 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1301 dest[STYLE_DENSITY] = config.density;
1302
1303 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1304 indicesIdx++;
1305 indices[indicesIdx] = ii;
1306 }
1307
1308 dest += STYLE_NUM_ENTRIES;
1309 }
1310
1311 res.unlock();
1312
1313 if (indices != NULL) {
1314 indices[0] = indicesIdx;
1315 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1316 }
1317 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1318 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1319 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1320
1321 return JNI_TRUE;
1322}
1323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001325 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 jint defStyleAttr,
1327 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001328 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 jintArray attrs,
1330 jintArray outValues,
1331 jintArray outIndices)
1332{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001333 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001334 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001335 return JNI_FALSE;
1336 }
1337 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001338 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001339 return JNI_FALSE;
1340 }
1341 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001342 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 return JNI_FALSE;
1344 }
1345
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001346 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001347 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1348 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1349 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001350 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001351
Ashok Bhat896043d2014-01-17 16:02:38 +00001352 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001354 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001355 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 Res_value value;
1357
1358 const jsize NI = env->GetArrayLength(attrs);
1359 const jsize NV = env->GetArrayLength(outValues);
1360 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001361 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 return JNI_FALSE;
1363 }
1364
1365 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1366 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 return JNI_FALSE;
1368 }
1369
1370 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1371 jint* dest = baseDest;
1372 if (dest == NULL) {
1373 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 return JNI_FALSE;
1375 }
1376
1377 jint* indices = NULL;
1378 int indicesIdx = 0;
1379 if (outIndices != NULL) {
1380 if (env->GetArrayLength(outIndices) > NI) {
1381 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1382 }
1383 }
1384
1385 // Load default style from attribute, if specified...
1386 uint32_t defStyleBagTypeSetFlags = 0;
1387 if (defStyleAttr != 0) {
1388 Res_value value;
1389 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1390 if (value.dataType == Res_value::TYPE_REFERENCE) {
1391 defStyleRes = value.data;
1392 }
1393 }
1394 }
1395
1396 // Retrieve the style class associated with the current XML tag.
1397 int style = 0;
1398 uint32_t styleBagTypeSetFlags = 0;
1399 if (xmlParser != NULL) {
1400 ssize_t idx = xmlParser->indexOfStyle();
1401 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1402 if (value.dataType == value.TYPE_ATTRIBUTE) {
1403 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1404 value.dataType = Res_value::TYPE_NULL;
1405 }
1406 }
1407 if (value.dataType == value.TYPE_REFERENCE) {
1408 style = value.data;
1409 }
1410 }
1411 }
1412
1413 // Now lock down the resource object and start pulling stuff from it.
1414 res.lock();
1415
1416 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001417 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 uint32_t defStyleTypeSetFlags = 0;
1419 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001420 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001422 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1423 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424
1425 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001426 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001428 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001430 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1431 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001432
1433 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001435 XmlAttributeFinder xmlAttrFinder(xmlParser);
1436 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437
1438 // Now iterate through all of the attributes that the client has requested,
1439 // filling in each with whatever data we can find.
1440 ssize_t block = 0;
1441 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001442 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 const uint32_t curIdent = (uint32_t)src[ii];
1444
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001445 if (kDebugStyles) {
1446 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1447 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 // Try to find a value for this attribute... we prioritize values
1450 // coming from, first XML attributes, then XML style, then default
1451 // style, and finally the theme.
1452 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001453 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001455 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001457 // Walk through the xml attributes looking for the requested attribute.
1458 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1459 if (xmlAttrIdx != xmlAttrEnd) {
1460 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001462 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001463 if (kDebugStyles) {
1464 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1465 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001466 }
1467
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001468 if (value.dataType == Res_value::TYPE_NULL) {
1469 // Walk through the style class values looking for the requested attribute.
1470 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1471 if (styleAttrEntry != styleAttrEnd) {
1472 // We found the attribute we were looking for.
1473 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001475 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001476 if (kDebugStyles) {
1477 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1478 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 }
1481
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001482 if (value.dataType == Res_value::TYPE_NULL) {
1483 // Walk through the default style values looking for the requested attribute.
1484 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1485 if (defStyleAttrEntry != defStyleAttrEnd) {
1486 // We found the attribute we were looking for.
1487 block = defStyleAttrEntry->stringBlock;
1488 typeSetFlags = styleTypeSetFlags;
1489 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001490 if (kDebugStyles) {
1491 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 }
1495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 uint32_t resid = 0;
1497 if (value.dataType != Res_value::TYPE_NULL) {
1498 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001499 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1500 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001501 if (newBlock >= 0) {
1502 block = newBlock;
1503 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001504
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001505 if (kDebugStyles) {
1506 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1507 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 } else {
1509 // If we still don't have a value for this attribute, try to find
1510 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1512 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001513 if (kDebugStyles) {
1514 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1515 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001516 newBlock = res.resolveReference(&value, block, &resid,
1517 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001518 if (kThrowOnBadId) {
1519 if (newBlock == BAD_INDEX) {
1520 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1521 return JNI_FALSE;
1522 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001523 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001524
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001525 if (newBlock >= 0) {
1526 block = newBlock;
1527 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001528
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001529 if (kDebugStyles) {
1530 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533 }
1534
1535 // Deal with the special @null value -- it turns back to TYPE_NULL.
1536 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001537 if (kDebugStyles) {
1538 ALOGI("-> Setting to @null!");
1539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001541 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001542 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 }
1544
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001545 if (kDebugStyles) {
1546 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548
1549 // Write the final value back to Java.
1550 dest[STYLE_TYPE] = value.dataType;
1551 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001552 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1553 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 dest[STYLE_RESOURCE_ID] = resid;
1555 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001556 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1559 indicesIdx++;
1560 indices[indicesIdx] = ii;
1561 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 dest += STYLE_NUM_ENTRIES;
1564 }
1565
1566 res.unlock();
1567
1568 if (indices != NULL) {
1569 indices[0] = indicesIdx;
1570 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1571 }
1572 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1573 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1574
1575 return JNI_TRUE;
1576}
1577
1578static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001579 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 jintArray attrs,
1581 jintArray outValues,
1582 jintArray outIndices)
1583{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001584 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001586 return JNI_FALSE;
1587 }
1588 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001589 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001590 return JNI_FALSE;
1591 }
1592 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001593 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 return JNI_FALSE;
1595 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 AssetManager* am = assetManagerForJavaObject(env, clazz);
1598 if (am == NULL) {
1599 return JNI_FALSE;
1600 }
1601 const ResTable& res(am->getResources());
1602 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001603 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 const jsize NI = env->GetArrayLength(attrs);
1607 const jsize NV = env->GetArrayLength(outValues);
1608 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001609 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 return JNI_FALSE;
1611 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1614 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 return JNI_FALSE;
1616 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1619 jint* dest = baseDest;
1620 if (dest == NULL) {
1621 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 return JNI_FALSE;
1623 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 jint* indices = NULL;
1626 int indicesIdx = 0;
1627 if (outIndices != NULL) {
1628 if (env->GetArrayLength(outIndices) > NI) {
1629 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1630 }
1631 }
1632
1633 // Now lock down the resource object and start pulling stuff from it.
1634 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 // Retrieve the XML attributes, if requested.
1637 const jsize NX = xmlParser->getAttributeCount();
1638 jsize ix=0;
1639 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 // Now iterate through all of the attributes that the client has requested,
1644 // filling in each with whatever data we can find.
1645 ssize_t block = 0;
1646 uint32_t typeSetFlags;
1647 for (jsize ii=0; ii<NI; ii++) {
1648 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 // Try to find a value for this attribute...
1651 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001652 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001654 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001657 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 ix++;
1659 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1660 }
1661 // Retrieve the current XML attribute if it matches, and step to next.
1662 if (ix < NX && curIdent == curXmlAttr) {
1663 block = kXmlBlock;
1664 xmlParser->getAttributeValue(ix, &value);
1665 ix++;
1666 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1667 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1670 uint32_t resid = 0;
1671 if (value.dataType != Res_value::TYPE_NULL) {
1672 // Take care of resolving the found resource to its final value.
1673 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001674 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1675 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001676 if (kThrowOnBadId) {
1677 if (newBlock == BAD_INDEX) {
1678 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1679 return JNI_FALSE;
1680 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001681 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 if (newBlock >= 0) block = newBlock;
1683 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 // Deal with the special @null value -- it turns back to TYPE_NULL.
1686 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1687 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001688 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 // Write the final value back to Java.
1694 dest[STYLE_TYPE] = value.dataType;
1695 dest[STYLE_DATA] = value.data;
1696 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001697 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 dest[STYLE_RESOURCE_ID] = resid;
1699 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001700 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1703 indicesIdx++;
1704 indices[indicesIdx] = ii;
1705 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 dest += STYLE_NUM_ENTRIES;
1708 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 if (indices != NULL) {
1713 indices[0] = indicesIdx;
1714 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1715 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1718 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 return JNI_TRUE;
1721}
1722
1723static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1724 jint id)
1725{
1726 AssetManager* am = assetManagerForJavaObject(env, clazz);
1727 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001728 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 }
1730 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732 res.lock();
1733 const ResTable::bag_entry* defStyleEnt = NULL;
1734 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1735 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001736
Ashok Bhat896043d2014-01-17 16:02:38 +00001737 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738}
1739
1740static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1741 jint id,
1742 jintArray outValues)
1743{
1744 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001745 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 return JNI_FALSE;
1747 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 AssetManager* am = assetManagerForJavaObject(env, clazz);
1750 if (am == NULL) {
1751 return JNI_FALSE;
1752 }
1753 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001754 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 Res_value value;
1756 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1761 jint* dest = baseDest;
1762 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001763 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 return JNI_FALSE;
1765 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 // Now lock down the resource object and start pulling stuff from it.
1768 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 const ResTable::bag_entry* arrayEnt = NULL;
1771 uint32_t arrayTypeSetFlags = 0;
1772 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1773 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1774 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 int i = 0;
1777 uint32_t typeSetFlags;
1778 while (i < NV && arrayEnt < endArrayEnt) {
1779 block = arrayEnt->stringBlock;
1780 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001781 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 uint32_t resid = 0;
1785 if (value.dataType != Res_value::TYPE_NULL) {
1786 // Take care of resolving the found resource to its final value.
1787 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001788 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1789 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001790 if (kThrowOnBadId) {
1791 if (newBlock == BAD_INDEX) {
1792 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1793 return JNI_FALSE;
1794 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 if (newBlock >= 0) block = newBlock;
1797 }
1798
1799 // Deal with the special @null value -- it turns back to TYPE_NULL.
1800 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1801 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001802 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 }
1804
1805 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1806
1807 // Write the final value back to Java.
1808 dest[STYLE_TYPE] = value.dataType;
1809 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001810 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 dest[STYLE_RESOURCE_ID] = resid;
1812 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001813 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 dest += STYLE_NUM_ENTRIES;
1815 i+= STYLE_NUM_ENTRIES;
1816 arrayEnt++;
1817 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001821 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 return i;
1826}
1827
Ashok Bhat896043d2014-01-17 16:02:38 +00001828static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 jint cookie,
1830 jstring fileName)
1831{
1832 AssetManager* am = assetManagerForJavaObject(env, clazz);
1833 if (am == NULL) {
1834 return 0;
1835 }
1836
Steve Block71f2cf12011-10-20 11:56:00 +01001837 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838
Elliott Hughes69a017b2011-04-08 14:10:28 -07001839 ScopedUtfChars fileName8(env, fileName);
1840 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 return 0;
1842 }
1843
Adam Lesinskide898ff2014-01-29 18:20:45 -08001844 int32_t assetCookie = static_cast<int32_t>(cookie);
1845 Asset* a = assetCookie
1846 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1847 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848
1849 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001850 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 return 0;
1852 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853
Adam Lesinskide898ff2014-01-29 18:20:45 -08001854 const DynamicRefTable* dynamicRefTable =
1855 am->getResources().getDynamicRefTableForCookie(assetCookie);
1856 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1858 a->close();
1859 delete a;
1860
1861 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001862 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 return 0;
1864 }
1865
Ashok Bhat896043d2014-01-17 16:02:38 +00001866 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867}
1868
1869static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1870 jint arrayResId)
1871{
1872 AssetManager* am = assetManagerForJavaObject(env, clazz);
1873 if (am == NULL) {
1874 return NULL;
1875 }
1876 const ResTable& res(am->getResources());
1877
1878 const ResTable::bag_entry* startOfBag;
1879 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1880 if (N < 0) {
1881 return NULL;
1882 }
1883
1884 jintArray array = env->NewIntArray(N * 2);
1885 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 res.unlockBag(startOfBag);
1887 return NULL;
1888 }
1889
1890 Res_value value;
1891 const ResTable::bag_entry* bag = startOfBag;
1892 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1893 jint stringIndex = -1;
1894 jint stringBlock = 0;
1895 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 // Take care of resolving the found resource to its final value.
1898 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1899 if (value.dataType == Res_value::TYPE_STRING) {
1900 stringIndex = value.data;
1901 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001902
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001903 if (kThrowOnBadId) {
1904 if (stringBlock == BAD_INDEX) {
1905 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1906 return array;
1907 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001908 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 //todo: It might be faster to allocate a C array to contain
1911 // the blocknums and indices, put them in there and then
1912 // do just one SetIntArrayRegion()
1913 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1914 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1915 j = j + 2;
1916 }
1917 res.unlockBag(startOfBag);
1918 return array;
1919}
1920
1921static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1922 jint arrayResId)
1923{
1924 AssetManager* am = assetManagerForJavaObject(env, clazz);
1925 if (am == NULL) {
1926 return NULL;
1927 }
1928 const ResTable& res(am->getResources());
1929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 const ResTable::bag_entry* startOfBag;
1931 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1932 if (N < 0) {
1933 return NULL;
1934 }
1935
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001936 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001937 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 res.unlockBag(startOfBag);
1939 return NULL;
1940 }
1941
1942 Res_value value;
1943 const ResTable::bag_entry* bag = startOfBag;
1944 size_t strLen = 0;
1945 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1946 value = bag->map.value;
1947 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 // Take care of resolving the found resource to its final value.
1950 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001951 if (kThrowOnBadId) {
1952 if (block == BAD_INDEX) {
1953 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1954 return array;
1955 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001958 const ResStringPool* pool = res.getTableStringBlock(block);
1959 const char* str8 = pool->string8At(value.data, &strLen);
1960 if (str8 != NULL) {
1961 str = env->NewStringUTF(str8);
1962 } else {
1963 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001964 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1965 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001966 }
1967
1968 // If one of our NewString{UTF} calls failed due to memory, an
1969 // exception will be pending.
1970 if (env->ExceptionCheck()) {
1971 res.unlockBag(startOfBag);
1972 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 }
Kenny Root780d2a12010-02-22 22:36:26 -08001974
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001975 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001976
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001977 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1978 // If we have a large amount of strings in our array, we might
1979 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001980 env->DeleteLocalRef(str);
1981 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001982 }
1983 res.unlockBag(startOfBag);
1984 return array;
1985}
1986
1987static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1988 jint arrayResId)
1989{
1990 AssetManager* am = assetManagerForJavaObject(env, clazz);
1991 if (am == NULL) {
1992 return NULL;
1993 }
1994 const ResTable& res(am->getResources());
1995
1996 const ResTable::bag_entry* startOfBag;
1997 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1998 if (N < 0) {
1999 return NULL;
2000 }
2001
2002 jintArray array = env->NewIntArray(N);
2003 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 res.unlockBag(startOfBag);
2005 return NULL;
2006 }
2007
2008 Res_value value;
2009 const ResTable::bag_entry* bag = startOfBag;
2010 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2011 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07002012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 // Take care of resolving the found resource to its final value.
2014 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08002015 if (kThrowOnBadId) {
2016 if (block == BAD_INDEX) {
2017 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
2018 return array;
2019 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002020 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 if (value.dataType >= Res_value::TYPE_FIRST_INT
2022 && value.dataType <= Res_value::TYPE_LAST_INT) {
2023 int intVal = value.data;
2024 env->SetIntArrayRegion(array, i, 1, &intVal);
2025 }
2026 }
2027 res.unlockBag(startOfBag);
2028 return array;
2029}
2030
Jon Miranda042ad632014-09-03 17:57:35 -07002031static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
2032 jint styleId)
2033{
2034 AssetManager* am = assetManagerForJavaObject(env, clazz);
2035 if (am == NULL) {
2036 return NULL;
2037 }
2038 const ResTable& res(am->getResources());
2039
2040 const ResTable::bag_entry* startOfBag;
2041 const ssize_t N = res.lockBag(styleId, &startOfBag);
2042 if (N < 0) {
2043 return NULL;
2044 }
2045
2046 jintArray array = env->NewIntArray(N);
2047 if (array == NULL) {
2048 res.unlockBag(startOfBag);
2049 return NULL;
2050 }
2051
Jon Miranda042ad632014-09-03 17:57:35 -07002052 const ResTable::bag_entry* bag = startOfBag;
2053 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2054 int resourceId = bag->map.name.ident;
2055 env->SetIntArrayRegion(array, i, 1, &resourceId);
2056 }
2057 res.unlockBag(startOfBag);
2058 return array;
2059}
2060
Mårten Kongstad48d22322014-01-31 14:43:27 +01002061static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002063 if (isSystem) {
2064 verifySystemIdmaps();
2065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 AssetManager* am = new AssetManager();
2067 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002068 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 return;
2070 }
2071
2072 am->addDefaultAssets();
2073
Steve Block71f2cf12011-10-20 11:56:00 +01002074 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002075 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076}
2077
2078static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2079{
2080 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002081 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002082 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 if (am != NULL) {
2084 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002085 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 }
2087}
2088
2089static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2090{
2091 return Asset::getGlobalCount();
2092}
2093
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002094static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2095{
2096 String8 alloc = Asset::getAssetAllocations();
2097 if (alloc.length() <= 0) {
2098 return NULL;
2099 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002100
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002101 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002102 return str;
2103}
2104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2106{
2107 return AssetManager::getGlobalCount();
2108}
2109
2110// ----------------------------------------------------------------------------
2111
2112/*
2113 * JNI registration.
2114 */
2115static JNINativeMethod gAssetManagerMethods[] = {
2116 /* name, signature, funcPtr */
2117
2118 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002119 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 (void*) android_content_AssetManager_openAsset },
2121 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2122 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002123 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002124 (void*) android_content_AssetManager_openNonAssetNative },
2125 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2126 (void*) android_content_AssetManager_openNonAssetFdNative },
2127 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2128 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002129 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002131 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002133 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002134 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002135 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002137 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002139 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002141 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002143 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002144 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 { "isUpToDate", "()Z",
2146 (void*) android_content_AssetManager_isUpToDate },
2147
2148 // Resources.
2149 { "setLocale", "(Ljava/lang/String;)V",
2150 (void*) android_content_AssetManager_setLocale },
2151 { "getLocales", "()[Ljava/lang/String;",
2152 (void*) android_content_AssetManager_getLocales },
Filip Gruszczynski23493322015-07-29 17:02:59 -07002153 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
2154 (void*) android_content_AssetManager_getSizeConfigurations },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002155 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 (void*) android_content_AssetManager_setConfiguration },
2157 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2158 (void*) android_content_AssetManager_getResourceIdentifier },
2159 { "getResourceName","(I)Ljava/lang/String;",
2160 (void*) android_content_AssetManager_getResourceName },
2161 { "getResourcePackageName","(I)Ljava/lang/String;",
2162 (void*) android_content_AssetManager_getResourcePackageName },
2163 { "getResourceTypeName","(I)Ljava/lang/String;",
2164 (void*) android_content_AssetManager_getResourceTypeName },
2165 { "getResourceEntryName","(I)Ljava/lang/String;",
2166 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002167 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 (void*) android_content_AssetManager_loadResourceValue },
2169 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2170 (void*) android_content_AssetManager_loadResourceBagValue },
2171 { "getStringBlockCount","()I",
2172 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002173 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 (void*) android_content_AssetManager_getNativeStringBlock },
2175 { "getCookieName","(I)Ljava/lang/String;",
2176 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002177 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2178 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179
2180 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002181 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002183 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002185 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002187 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002189 { "clearTheme", "(J)V",
2190 (void*) android_content_AssetManager_clearTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002191 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 (void*) android_content_AssetManager_loadThemeAttributeValue },
Alan Viverettec1d52792015-05-05 09:49:03 -07002193 { "getThemeChangingConfigurations", "(J)I",
2194 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002195 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002197 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002199 { "resolveAttrs","(JII[I[I[I[I)Z",
2200 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002201 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 (void*) android_content_AssetManager_retrieveAttributes },
2203 { "getArraySize","(I)I",
2204 (void*) android_content_AssetManager_getArraySize },
2205 { "retrieveArray","(I[I)I",
2206 (void*) android_content_AssetManager_retrieveArray },
2207
2208 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002209 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 (void*) android_content_AssetManager_openXmlAssetNative },
2211
2212 // Arrays.
2213 { "getArrayStringResource","(I)[Ljava/lang/String;",
2214 (void*) android_content_AssetManager_getArrayStringResource },
2215 { "getArrayStringInfo","(I)[I",
2216 (void*) android_content_AssetManager_getArrayStringInfo },
2217 { "getArrayIntResource","(I)[I",
2218 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002219 { "getStyleAttributes","(I)[I",
2220 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221
2222 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002223 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 (void*) android_content_AssetManager_init },
2225 { "destroy", "()V",
2226 (void*) android_content_AssetManager_destroy },
2227 { "getGlobalAssetCount", "()I",
2228 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002229 { "getAssetAllocations", "()Ljava/lang/String;",
2230 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002231 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002232 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002233};
2234
2235int register_android_content_AssetManager(JNIEnv* env)
2236{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002237 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2238 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2239 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2240 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2241 "Ljava/lang/CharSequence;");
2242 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2243 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2244 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2245 "changingConfigurations", "I");
2246 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247
Andreas Gampe987f79f2014-11-18 17:29:46 -08002248 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2249 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2250 "Landroid/os/ParcelFileDescriptor;");
2251 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2252 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253
Andreas Gampe987f79f2014-11-18 17:29:46 -08002254 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2255 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256
Andreas Gampe987f79f2014-11-18 17:29:46 -08002257 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2258 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259
Andreas Gampe987f79f2014-11-18 17:29:46 -08002260 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2261 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2262 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2263 "<init>", "()V");
2264 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2265 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002266
Filip Gruszczynski23493322015-07-29 17:02:59 -07002267 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
2268 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
2269 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
2270 "<init>", "()V");
2271 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2272 "smallestScreenWidthDp", "I");
2273 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2274 "screenWidthDp", "I");
2275 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
2276 "screenHeightDp", "I");
2277
Andreas Gampe987f79f2014-11-18 17:29:46 -08002278 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2279 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280}
2281
2282}; // namespace android