blob: 8385f75e4a661406ca2f1bb61316871d7006243b [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>
Mårten Kongstad83ab0d72015-03-20 12:57:36 +010027#include <sys/stat.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010028
Dan Albert46d84442014-11-18 16:07:51 -080029#include <private/android_filesystem_config.h> // for AID_SYSTEM
30
Dan Albert3a091b72014-11-20 15:41:25 -080031#include "androidfw/Asset.h"
32#include "androidfw/AssetManager.h"
33#include "androidfw/AttributeFinder.h"
34#include "androidfw/ResourceTypes.h"
35#include "android_runtime/AndroidRuntime.h"
36#include "android_util_Binder.h"
37#include "core_jni_helpers.h"
38#include "jni.h"
Dan Albert46d84442014-11-18 16:07:51 -080039#include "JNIHelp.h"
40#include "ScopedStringChars.h"
41#include "ScopedUtfChars.h"
Dan Albert46d84442014-11-18 16:07:51 -080042#include "utils/Log.h"
43#include "utils/misc.h"
44
Mårten Kongstad48d22322014-01-31 14:43:27 +010045extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
46extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
47
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
49namespace android {
50
Andreas Gampe0f0b4912014-11-12 08:03:48 -080051static const bool kThrowOnBadId = false;
52static const bool kDebugStyles = false;
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054// ----------------------------------------------------------------------------
55
56static struct typedvalue_offsets_t
57{
58 jfieldID mType;
59 jfieldID mData;
60 jfieldID mString;
61 jfieldID mAssetCookie;
62 jfieldID mResourceId;
63 jfieldID mChangingConfigurations;
64 jfieldID mDensity;
65} gTypedValueOffsets;
66
67static struct assetfiledescriptor_offsets_t
68{
69 jfieldID mFd;
70 jfieldID mStartOffset;
71 jfieldID mLength;
72} gAssetFileDescriptorOffsets;
73
74static struct assetmanager_offsets_t
75{
76 jfieldID mObject;
77} gAssetManagerOffsets;
78
Adam Lesinskide898ff2014-01-29 18:20:45 -080079static struct sparsearray_offsets_t
80{
81 jclass classObject;
82 jmethodID constructor;
83 jmethodID put;
84} gSparseArrayOffsets;
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086jclass g_stringClass = NULL;
87
88// ----------------------------------------------------------------------------
89
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070091 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 STYLE_TYPE = 0,
93 STYLE_DATA = 1,
94 STYLE_ASSET_COOKIE = 2,
95 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070096 STYLE_CHANGING_CONFIGURATIONS = 4,
97 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098};
99
100static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
101 const Res_value& value, uint32_t ref, ssize_t block,
102 uint32_t typeSpecFlags, ResTable_config* config = NULL);
103
104jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
105 const Res_value& value, uint32_t ref, ssize_t block,
106 uint32_t typeSpecFlags, ResTable_config* config)
107{
108 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
109 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000110 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
112 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
113 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
114 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
115 typeSpecFlags);
116 if (config != NULL) {
117 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
118 }
119 return block;
120}
121
Mårten Kongstad48d22322014-01-31 14:43:27 +0100122// This is called by zygote (running as user root) as part of preloadResources.
123static void verifySystemIdmaps()
124{
125 pid_t pid;
126 char system_id[10];
127
128 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
129
130 switch (pid = fork()) {
131 case -1:
132 ALOGE("failed to fork for idmap: %s", strerror(errno));
133 break;
134 case 0: // child
135 {
136 struct __user_cap_header_struct capheader;
137 struct __user_cap_data_struct capdata;
138
139 memset(&capheader, 0, sizeof(capheader));
140 memset(&capdata, 0, sizeof(capdata));
141
142 capheader.version = _LINUX_CAPABILITY_VERSION;
143 capheader.pid = 0;
144
145 if (capget(&capheader, &capdata) != 0) {
146 ALOGE("capget: %s\n", strerror(errno));
147 exit(1);
148 }
149
150 capdata.effective = capdata.permitted;
151 if (capset(&capheader, &capdata) != 0) {
152 ALOGE("capset: %s\n", strerror(errno));
153 exit(1);
154 }
155
156 if (setgid(AID_SYSTEM) != 0) {
157 ALOGE("setgid: %s\n", strerror(errno));
158 exit(1);
159 }
160
161 if (setuid(AID_SYSTEM) != 0) {
162 ALOGE("setuid: %s\n", strerror(errno));
163 exit(1);
164 }
165
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100166 // Generic idmap parameters
167 const char* argv[7];
168 int argc = 0;
169 struct stat st;
170
171 memset(argv, NULL, sizeof(argv));
172 argv[argc++] = AssetManager::IDMAP_BIN;
173 argv[argc++] = "--scan";
174 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
175 argv[argc++] = AssetManager::TARGET_APK_PATH;
176 argv[argc++] = AssetManager::IDMAP_DIR;
177
178 // Directories to scan for overlays
179 // /vendor/overlay
180 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
181 argv[argc++] = AssetManager::OVERLAY_DIR;
182 }
183
184 // Finally, invoke idmap (if any overlay directory exists)
185 if (argc > 5) {
186 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
187 ALOGE("failed to execl for idmap: %s", strerror(errno));
188 exit(1); // should never get here
189 } else {
190 exit(0);
191 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100192 }
193 break;
194 default: // parent
195 waitpid(pid, NULL, 0);
196 break;
197 }
198}
199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200// ----------------------------------------------------------------------------
201
202// this guy is exported to other jni routines
203AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
204{
Ashok Bhat896043d2014-01-17 16:02:38 +0000205 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
206 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 if (am != NULL) {
208 return am;
209 }
210 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
211 return NULL;
212}
213
Ashok Bhat896043d2014-01-17 16:02:38 +0000214static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 jstring fileName, jint mode)
216{
217 AssetManager* am = assetManagerForJavaObject(env, clazz);
218 if (am == NULL) {
219 return 0;
220 }
221
Steve Block71f2cf12011-10-20 11:56:00 +0100222 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
Elliott Hughes69a017b2011-04-08 14:10:28 -0700224 ScopedUtfChars fileName8(env, fileName);
225 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000226 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 return -1;
228 }
229
230 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
231 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700232 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 return -1;
234 }
235
Elliott Hughes69a017b2011-04-08 14:10:28 -0700236 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237
238 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700239 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 return -1;
241 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
243 //printf("Created Asset Stream: %p\n", a);
244
Ashok Bhat896043d2014-01-17 16:02:38 +0000245 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246}
247
248static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
249{
Kenny Rootddb76c42010-11-24 12:56:06 -0800250 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 int fd = a->openFileDescriptor(&startOffset, &length);
252 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700255 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 "This file can not be opened as a file descriptor; it is probably compressed");
257 return NULL;
258 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
261 if (offsets == NULL) {
262 close(fd);
263 return NULL;
264 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 offsets[0] = startOffset;
267 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700270
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700271 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 if (fileDesc == NULL) {
273 close(fd);
274 return NULL;
275 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 return newParcelFileDescriptor(env, fileDesc);
278}
279
280static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
281 jstring fileName, jlongArray outOffsets)
282{
283 AssetManager* am = assetManagerForJavaObject(env, clazz);
284 if (am == NULL) {
285 return NULL;
286 }
287
Steve Block71f2cf12011-10-20 11:56:00 +0100288 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289
Elliott Hughes69a017b2011-04-08 14:10:28 -0700290 ScopedUtfChars fileName8(env, fileName);
291 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 return NULL;
293 }
294
Elliott Hughes69a017b2011-04-08 14:10:28 -0700295 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
297 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700298 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 return NULL;
300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301
302 //printf("Created Asset Stream: %p\n", a);
303
304 return returnParcelFileDescriptor(env, a, outOffsets);
305}
306
Ashok Bhat896043d2014-01-17 16:02:38 +0000307static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 jint cookie,
309 jstring fileName,
310 jint mode)
311{
312 AssetManager* am = assetManagerForJavaObject(env, clazz);
313 if (am == NULL) {
314 return 0;
315 }
316
Steve Block71f2cf12011-10-20 11:56:00 +0100317 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318
Elliott Hughes69a017b2011-04-08 14:10:28 -0700319 ScopedUtfChars fileName8(env, fileName);
320 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 return -1;
322 }
323
324 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
325 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700326 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 return -1;
328 }
329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000331 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
332 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700333 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334
335 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700336 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 return -1;
338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
340 //printf("Created Asset Stream: %p\n", a);
341
Ashok Bhat896043d2014-01-17 16:02:38 +0000342 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343}
344
345static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
346 jint cookie,
347 jstring fileName,
348 jlongArray outOffsets)
349{
350 AssetManager* am = assetManagerForJavaObject(env, clazz);
351 if (am == NULL) {
352 return NULL;
353 }
354
Steve Block71f2cf12011-10-20 11:56:00 +0100355 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356
Elliott Hughes69a017b2011-04-08 14:10:28 -0700357 ScopedUtfChars fileName8(env, fileName);
358 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 return NULL;
360 }
361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000363 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700364 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
366 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700367 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 return NULL;
369 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370
371 //printf("Created Asset Stream: %p\n", a);
372
373 return returnParcelFileDescriptor(env, a, outOffsets);
374}
375
376static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
377 jstring fileName)
378{
379 AssetManager* am = assetManagerForJavaObject(env, clazz);
380 if (am == NULL) {
381 return NULL;
382 }
383
Elliott Hughes69a017b2011-04-08 14:10:28 -0700384 ScopedUtfChars fileName8(env, fileName);
385 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 return NULL;
387 }
388
Elliott Hughes69a017b2011-04-08 14:10:28 -0700389 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390
391 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700392 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 return NULL;
394 }
395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 size_t N = dir->getFileCount();
397
398 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100399 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 delete dir;
402 return NULL;
403 }
404
405 for (size_t i=0; i<N; i++) {
406 const String8& name = dir->getFileName(i);
407 jstring str = env->NewStringUTF(name.string());
408 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 delete dir;
410 return NULL;
411 }
412 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700413 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 }
415
416 delete dir;
417
418 return array;
419}
420
421static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000422 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423{
Ashok Bhat896043d2014-01-17 16:02:38 +0000424 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425
426 //printf("Destroying Asset Stream: %p\n", a);
427
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;
431 }
432
433 delete a;
434}
435
436static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000437 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438{
Ashok Bhat896043d2014-01-17 16:02:38 +0000439 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440
441 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700442 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 return -1;
444 }
445
446 uint8_t b;
447 ssize_t res = a->read(&b, 1);
448 return res == 1 ? b : -1;
449}
450
451static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000452 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 jint off, jint len)
454{
Ashok Bhat896043d2014-01-17 16:02:38 +0000455 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456
457 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700458 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 return -1;
460 }
461
462 if (len == 0) {
463 return 0;
464 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 jsize bLen = env->GetArrayLength(bArray);
467 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700468 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 return -1;
470 }
471
472 jbyte* b = env->GetByteArrayElements(bArray, NULL);
473 ssize_t res = a->read(b+off, len);
474 env->ReleaseByteArrayElements(bArray, b, 0);
475
Ashok Bhat896043d2014-01-17 16:02:38 +0000476 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477
478 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700479 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 }
481 return -1;
482}
483
484static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000485 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 jlong offset, jint whence)
487{
Ashok Bhat896043d2014-01-17 16:02:38 +0000488 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489
490 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700491 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 return -1;
493 }
494
495 return a->seek(
496 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
497}
498
499static jlong android_content_AssetManager_getAssetLength(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->getLength();
510}
511
512static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000513 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514{
Ashok Bhat896043d2014-01-17 16:02:38 +0000515 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516
517 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700518 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 return -1;
520 }
521
522 return a->getRemainingLength();
523}
524
525static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
526 jstring path)
527{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700528 ScopedUtfChars path8(env, path);
529 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800530 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 }
532
533 AssetManager* am = assetManagerForJavaObject(env, clazz);
534 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800535 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536 }
537
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000538 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700539 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000541 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542}
543
Mårten Kongstad48d22322014-01-31 14:43:27 +0100544static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
545 jstring idmapPath)
546{
547 ScopedUtfChars idmapPath8(env, idmapPath);
548 if (idmapPath8.c_str() == NULL) {
549 return 0;
550 }
551
552 AssetManager* am = assetManagerForJavaObject(env, clazz);
553 if (am == NULL) {
554 return 0;
555 }
556
557 int32_t cookie;
558 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
559
560 return (res) ? (jint)cookie : 0;
561}
562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
564{
565 AssetManager* am = assetManagerForJavaObject(env, clazz);
566 if (am == NULL) {
567 return JNI_TRUE;
568 }
569 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
570}
571
572static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
573 jstring locale)
574{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700575 ScopedUtfChars locale8(env, locale);
576 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 return;
578 }
579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 AssetManager* am = assetManagerForJavaObject(env, clazz);
581 if (am == NULL) {
582 return;
583 }
584
Elliott Hughes69a017b2011-04-08 14:10:28 -0700585 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800586}
587
588static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
589{
590 Vector<String8> locales;
591
592 AssetManager* am = assetManagerForJavaObject(env, clazz);
593 if (am == NULL) {
594 return NULL;
595 }
596
597 am->getLocales(&locales);
598
599 const int N = locales.size();
600
601 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
602 if (result == NULL) {
603 return NULL;
604 }
605
606 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700607 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700608 if (str == NULL) {
609 return NULL;
610 }
611 env->SetObjectArrayElement(result, i, str);
612 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 }
614
615 return result;
616}
617
618static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
619 jint mcc, jint mnc,
620 jstring locale, jint orientation,
621 jint touchscreen, jint density,
622 jint keyboard, jint keyboardHidden,
623 jint navigation,
624 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700625 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700626 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100627 jint screenLayout, jint uiMode,
628 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629{
630 AssetManager* am = assetManagerForJavaObject(env, clazz);
631 if (am == NULL) {
632 return;
633 }
634
635 ResTable_config config;
636 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700639
Adam Lesinski2738c962015-05-14 14:25:36 -0700640 // Constants duplicated from Java class android.content.res.Configuration.
641 static const jint kScreenLayoutRoundMask = 0x300;
642 static const jint kScreenLayoutRoundShift = 8;
643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800644 config.mcc = (uint16_t)mcc;
645 config.mnc = (uint16_t)mnc;
646 config.orientation = (uint8_t)orientation;
647 config.touchscreen = (uint8_t)touchscreen;
648 config.density = (uint16_t)density;
649 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700650 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 config.navigation = (uint8_t)navigation;
652 config.screenWidth = (uint16_t)screenWidth;
653 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700654 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700655 config.screenWidthDp = (uint16_t)screenWidthDp;
656 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700657 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100658 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 config.sdkVersion = (uint16_t)sdkVersion;
660 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700661
662 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
663 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
664 // into screenLayout2.
665 config.screenLayout2 =
666 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
671}
672
673static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
674 jstring name,
675 jstring defType,
676 jstring defPackage)
677{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700678 ScopedStringChars name16(env, name);
679 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 return 0;
681 }
682
683 AssetManager* am = assetManagerForJavaObject(env, clazz);
684 if (am == NULL) {
685 return 0;
686 }
687
Dan Albert66987492014-11-20 11:41:21 -0800688 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
689 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
690 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 jsize defTypeLen = defType
692 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800693 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
694 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
695 NULL))
696 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 jsize defPackageLen = defPackage
698 ? env->GetStringLength(defPackage) : 0;
699
700 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800701 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
702 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703
704 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800705 env->ReleaseStringChars(defPackage,
706 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 }
708 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800709 env->ReleaseStringChars(defType,
710 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
713 return ident;
714}
715
716static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
717 jint resid)
718{
719 AssetManager* am = assetManagerForJavaObject(env, clazz);
720 if (am == NULL) {
721 return NULL;
722 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700725 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 return NULL;
727 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 String16 str;
730 if (name.package != NULL) {
731 str.setTo(name.package, name.packageLen);
732 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700733 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 if (str.size() > 0) {
735 char16_t div = ':';
736 str.append(&div, 1);
737 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700738 if (name.type8 != NULL) {
739 str.append(String16(name.type8, name.typeLen));
740 } else {
741 str.append(name.type, name.typeLen);
742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700744 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 if (str.size() > 0) {
746 char16_t div = '/';
747 str.append(&div, 1);
748 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700749 if (name.name8 != NULL) {
750 str.append(String16(name.name8, name.nameLen));
751 } else {
752 str.append(name.name, name.nameLen);
753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 return env->NewString((const jchar*)str.string(), str.size());
757}
758
759static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
760 jint resid)
761{
762 AssetManager* am = assetManagerForJavaObject(env, clazz);
763 if (am == NULL) {
764 return NULL;
765 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700768 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 return NULL;
770 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 if (name.package != NULL) {
773 return env->NewString((const jchar*)name.package, name.packageLen);
774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 return NULL;
777}
778
779static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
780 jint resid)
781{
782 AssetManager* am = assetManagerForJavaObject(env, clazz);
783 if (am == NULL) {
784 return NULL;
785 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700788 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 return NULL;
790 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700791
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700792 if (name.type8 != NULL) {
793 return env->NewStringUTF(name.type8);
794 }
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 if (name.type != NULL) {
797 return env->NewString((const jchar*)name.type, name.typeLen);
798 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 return NULL;
801}
802
803static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
804 jint resid)
805{
806 AssetManager* am = assetManagerForJavaObject(env, clazz);
807 if (am == NULL) {
808 return NULL;
809 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700812 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 return NULL;
814 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700815
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700816 if (name.name8 != NULL) {
817 return env->NewStringUTF(name.name8);
818 }
819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 if (name.name != NULL) {
821 return env->NewString((const jchar*)name.name, name.nameLen);
822 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 return NULL;
825}
826
827static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
828 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700829 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 jobject outValue,
831 jboolean resolve)
832{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800833 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800834 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700835 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 AssetManager* am = assetManagerForJavaObject(env, clazz);
838 if (am == NULL) {
839 return 0;
840 }
841 const ResTable& res(am->getResources());
842
843 Res_value value;
844 ResTable_config config;
845 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700846 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800847 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800848 if (block == BAD_INDEX) {
849 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
850 return 0;
851 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800852 }
853 uint32_t ref = ident;
854 if (resolve) {
855 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
856 if (kThrowOnBadId) {
857 if (block == BAD_INDEX) {
858 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
859 return 0;
860 }
861 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000863 if (block >= 0) {
864 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
865 }
866
867 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868}
869
870static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
871 jint ident, jint bagEntryId,
872 jobject outValue, jboolean resolve)
873{
874 AssetManager* am = assetManagerForJavaObject(env, clazz);
875 if (am == NULL) {
876 return 0;
877 }
878 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 // Now lock down the resource object and start pulling stuff from it.
881 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 ssize_t block = -1;
884 Res_value value;
885
886 const ResTable::bag_entry* entry = NULL;
887 uint32_t typeSpecFlags;
888 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
889
890 for (ssize_t i=0; i<entryCount; i++) {
891 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
892 block = entry->stringBlock;
893 value = entry->map.value;
894 }
895 entry++;
896 }
897
898 res.unlock();
899
900 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000901 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800904 uint32_t ref = ident;
905 if (resolve) {
906 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800907 if (kThrowOnBadId) {
908 if (block == BAD_INDEX) {
909 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
910 return 0;
911 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000914 if (block >= 0) {
915 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
916 }
917
918 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919}
920
921static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
922{
923 AssetManager* am = assetManagerForJavaObject(env, clazz);
924 if (am == NULL) {
925 return 0;
926 }
927 return am->getResources().getTableCount();
928}
929
Ashok Bhat896043d2014-01-17 16:02:38 +0000930static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 jint block)
932{
933 AssetManager* am = assetManagerForJavaObject(env, clazz);
934 if (am == NULL) {
935 return 0;
936 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000937 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938}
939
940static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
941 jint cookie)
942{
943 AssetManager* am = assetManagerForJavaObject(env, clazz);
944 if (am == NULL) {
945 return NULL;
946 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000947 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700949 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 return NULL;
951 }
952 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 return str;
954}
955
Adam Lesinskide898ff2014-01-29 18:20:45 -0800956static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
957{
958 AssetManager* am = assetManagerForJavaObject(env, clazz);
959 if (am == NULL) {
960 return 0;
961 }
962
963 const ResTable& res = am->getResources();
964
965 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
966 gSparseArrayOffsets.constructor);
967 const size_t N = res.getBasePackageCount();
968 for (size_t i = 0; i < N; i++) {
969 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -0800970 env->CallVoidMethod(
971 sparseArray, gSparseArrayOffsets.put,
972 static_cast<jint>(res.getBasePackageId(i)),
973 env->NewString(reinterpret_cast<const jchar*>(name.string()),
974 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -0800975 }
976 return sparseArray;
977}
978
Ashok Bhat896043d2014-01-17 16:02:38 +0000979static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980{
981 AssetManager* am = assetManagerForJavaObject(env, clazz);
982 if (am == NULL) {
983 return 0;
984 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000985 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986}
987
988static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000989 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800990{
Ashok Bhat896043d2014-01-17 16:02:38 +0000991 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 delete theme;
993}
994
995static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000996 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 jint styleRes,
998 jboolean force)
999{
Ashok Bhat896043d2014-01-17 16:02:38 +00001000 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 theme->applyStyle(styleRes, force ? true : false);
1002}
1003
1004static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001005 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006{
Ashok Bhat896043d2014-01-17 16:02:38 +00001007 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1008 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 dest->setTo(*src);
1010}
1011
Alan Viverettee54d2452015-05-06 10:41:43 -07001012static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1013{
1014 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1015 theme->clear();
1016}
1017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001019 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020{
Ashok Bhat896043d2014-01-17 16:02:38 +00001021 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 const ResTable& res(theme->getResTable());
1023
1024 Res_value value;
1025 // XXX value could be different in different configs!
1026 uint32_t typeSpecFlags = 0;
1027 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1028 uint32_t ref = 0;
1029 if (resolve) {
1030 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001031 if (kThrowOnBadId) {
1032 if (block == BAD_INDEX) {
1033 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1034 return 0;
1035 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 }
1038 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1039}
1040
Alan Viverettec1d52792015-05-05 09:49:03 -07001041static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1042 jlong themeHandle)
1043{
1044 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1045 return theme->getChangingConfigurations();
1046}
1047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001049 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 jstring tag, jstring prefix)
1051{
Ashok Bhat896043d2014-01-17 16:02:38 +00001052 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001054 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 // XXX Need to use params.
1057 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058}
1059
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001060class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1061public:
1062 XmlAttributeFinder(const ResXMLParser* parser)
1063 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1064 , mParser(parser) {}
1065
1066 inline uint32_t getAttribute(jsize index) const {
1067 return mParser->getAttributeNameResID(index);
1068 }
1069
1070private:
1071 const ResXMLParser* mParser;
1072};
1073
1074class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1075public:
1076 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1077 : BackTrackingAttributeFinder(start, end) {}
1078
1079 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1080 return entry->map.name.ident;
1081 }
1082};
1083
Alan Viverette52b999f2014-03-24 18:00:26 -07001084static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1085 jlong themeToken,
1086 jint defStyleAttr,
1087 jint defStyleRes,
1088 jintArray inValues,
1089 jintArray attrs,
1090 jintArray outValues,
1091 jintArray outIndices)
1092{
1093 if (themeToken == 0) {
1094 jniThrowNullPointerException(env, "theme token");
1095 return JNI_FALSE;
1096 }
1097 if (attrs == NULL) {
1098 jniThrowNullPointerException(env, "attrs");
1099 return JNI_FALSE;
1100 }
1101 if (outValues == NULL) {
1102 jniThrowNullPointerException(env, "out values");
1103 return JNI_FALSE;
1104 }
1105
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001106 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001107 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1108 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001109 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001110
1111 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1112 const ResTable& res = theme->getResTable();
1113 ResTable_config config;
1114 Res_value value;
1115
1116 const jsize NI = env->GetArrayLength(attrs);
1117 const jsize NV = env->GetArrayLength(outValues);
1118 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1119 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1120 return JNI_FALSE;
1121 }
1122
1123 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1124 if (src == NULL) {
1125 return JNI_FALSE;
1126 }
1127
1128 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1129 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1130
1131 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1132 jint* dest = baseDest;
1133 if (dest == NULL) {
1134 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1135 return JNI_FALSE;
1136 }
1137
1138 jint* indices = NULL;
1139 int indicesIdx = 0;
1140 if (outIndices != NULL) {
1141 if (env->GetArrayLength(outIndices) > NI) {
1142 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1143 }
1144 }
1145
1146 // Load default style from attribute, if specified...
1147 uint32_t defStyleBagTypeSetFlags = 0;
1148 if (defStyleAttr != 0) {
1149 Res_value value;
1150 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1151 if (value.dataType == Res_value::TYPE_REFERENCE) {
1152 defStyleRes = value.data;
1153 }
1154 }
1155 }
1156
1157 // Now lock down the resource object and start pulling stuff from it.
1158 res.lock();
1159
1160 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001161 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001162 uint32_t defStyleTypeSetFlags = 0;
1163 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001164 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001165 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001166 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1167 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001168
1169 // Now iterate through all of the attributes that the client has requested,
1170 // filling in each with whatever data we can find.
1171 ssize_t block = 0;
1172 uint32_t typeSetFlags;
1173 for (jsize ii=0; ii<NI; ii++) {
1174 const uint32_t curIdent = (uint32_t)src[ii];
1175
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001176 if (kDebugStyles) {
1177 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1178 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001179
1180 // Try to find a value for this attribute... we prioritize values
1181 // coming from, first XML attributes, then XML style, then default
1182 // style, and finally the theme.
1183 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001184 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001185 typeSetFlags = 0;
1186 config.density = 0;
1187
1188 // Retrieve the current input value if available.
1189 if (NSV > 0 && srcValues[ii] != 0) {
1190 block = -1;
1191 value.dataType = Res_value::TYPE_ATTRIBUTE;
1192 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001193 if (kDebugStyles) {
1194 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1195 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001196 }
1197
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001198 if (value.dataType == Res_value::TYPE_NULL) {
1199 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1200 if (defStyleEntry != defStyleEnd) {
1201 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001202 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001203 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001204 if (kDebugStyles) {
1205 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1206 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001207 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001208 }
1209
1210 uint32_t resid = 0;
1211 if (value.dataType != Res_value::TYPE_NULL) {
1212 // Take care of resolving the found resource to its final value.
1213 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1214 &resid, &typeSetFlags, &config);
1215 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001216 if (kDebugStyles) {
1217 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1218 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001219 } else {
1220 // If we still don't have a value for this attribute, try to find
1221 // it in the theme!
1222 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1223 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001224 if (kDebugStyles) {
1225 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1226 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001227 newBlock = res.resolveReference(&value, block, &resid,
1228 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001229 if (kThrowOnBadId) {
1230 if (newBlock == BAD_INDEX) {
1231 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1232 return JNI_FALSE;
1233 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001234 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001235 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001236 if (kDebugStyles) {
1237 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1238 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001239 }
1240 }
1241
1242 // Deal with the special @null value -- it turns back to TYPE_NULL.
1243 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001244 if (kDebugStyles) {
1245 ALOGI("-> Setting to @null!");
1246 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001247 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001248 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001249 block = -1;
1250 }
1251
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001252 if (kDebugStyles) {
1253 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1254 value.data);
1255 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001256
1257 // Write the final value back to Java.
1258 dest[STYLE_TYPE] = value.dataType;
1259 dest[STYLE_DATA] = value.data;
1260 dest[STYLE_ASSET_COOKIE] =
1261 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1262 dest[STYLE_RESOURCE_ID] = resid;
1263 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1264 dest[STYLE_DENSITY] = config.density;
1265
1266 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1267 indicesIdx++;
1268 indices[indicesIdx] = ii;
1269 }
1270
1271 dest += STYLE_NUM_ENTRIES;
1272 }
1273
1274 res.unlock();
1275
1276 if (indices != NULL) {
1277 indices[0] = indicesIdx;
1278 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1279 }
1280 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1281 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1282 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1283
1284 return JNI_TRUE;
1285}
1286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001288 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 jint defStyleAttr,
1290 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001291 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 jintArray attrs,
1293 jintArray outValues,
1294 jintArray outIndices)
1295{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001296 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001297 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001298 return JNI_FALSE;
1299 }
1300 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001301 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001302 return JNI_FALSE;
1303 }
1304 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001305 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 return JNI_FALSE;
1307 }
1308
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001309 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001310 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1311 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1312 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001313 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001314
Ashok Bhat896043d2014-01-17 16:02:38 +00001315 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001317 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001318 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 Res_value value;
1320
1321 const jsize NI = env->GetArrayLength(attrs);
1322 const jsize NV = env->GetArrayLength(outValues);
1323 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001324 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 return JNI_FALSE;
1326 }
1327
1328 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1329 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 return JNI_FALSE;
1331 }
1332
1333 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1334 jint* dest = baseDest;
1335 if (dest == NULL) {
1336 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 return JNI_FALSE;
1338 }
1339
1340 jint* indices = NULL;
1341 int indicesIdx = 0;
1342 if (outIndices != NULL) {
1343 if (env->GetArrayLength(outIndices) > NI) {
1344 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1345 }
1346 }
1347
1348 // Load default style from attribute, if specified...
1349 uint32_t defStyleBagTypeSetFlags = 0;
1350 if (defStyleAttr != 0) {
1351 Res_value value;
1352 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1353 if (value.dataType == Res_value::TYPE_REFERENCE) {
1354 defStyleRes = value.data;
1355 }
1356 }
1357 }
1358
1359 // Retrieve the style class associated with the current XML tag.
1360 int style = 0;
1361 uint32_t styleBagTypeSetFlags = 0;
1362 if (xmlParser != NULL) {
1363 ssize_t idx = xmlParser->indexOfStyle();
1364 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1365 if (value.dataType == value.TYPE_ATTRIBUTE) {
1366 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1367 value.dataType = Res_value::TYPE_NULL;
1368 }
1369 }
1370 if (value.dataType == value.TYPE_REFERENCE) {
1371 style = value.data;
1372 }
1373 }
1374 }
1375
1376 // Now lock down the resource object and start pulling stuff from it.
1377 res.lock();
1378
1379 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001380 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 uint32_t defStyleTypeSetFlags = 0;
1382 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001383 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001385 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1386 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387
1388 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001389 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001391 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001393 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1394 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395
1396 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001398 XmlAttributeFinder xmlAttrFinder(xmlParser);
1399 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400
1401 // Now iterate through all of the attributes that the client has requested,
1402 // filling in each with whatever data we can find.
1403 ssize_t block = 0;
1404 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001405 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 const uint32_t curIdent = (uint32_t)src[ii];
1407
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001408 if (kDebugStyles) {
1409 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1410 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 // Try to find a value for this attribute... we prioritize values
1413 // coming from, first XML attributes, then XML style, then default
1414 // style, and finally the theme.
1415 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001416 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001418 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001420 // Walk through the xml attributes looking for the requested attribute.
1421 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1422 if (xmlAttrIdx != xmlAttrEnd) {
1423 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001425 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001426 if (kDebugStyles) {
1427 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1428 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001429 }
1430
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001431 if (value.dataType == Res_value::TYPE_NULL) {
1432 // Walk through the style class values looking for the requested attribute.
1433 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1434 if (styleAttrEntry != styleAttrEnd) {
1435 // We found the attribute we were looking for.
1436 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001438 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001439 if (kDebugStyles) {
1440 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 }
1444
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001445 if (value.dataType == Res_value::TYPE_NULL) {
1446 // Walk through the default style values looking for the requested attribute.
1447 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1448 if (defStyleAttrEntry != defStyleAttrEnd) {
1449 // We found the attribute we were looking for.
1450 block = defStyleAttrEntry->stringBlock;
1451 typeSetFlags = styleTypeSetFlags;
1452 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001453 if (kDebugStyles) {
1454 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1455 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 }
1458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 uint32_t resid = 0;
1460 if (value.dataType != Res_value::TYPE_NULL) {
1461 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001462 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1463 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001464 if (newBlock >= 0) {
1465 block = newBlock;
1466 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001467
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001468 if (kDebugStyles) {
1469 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 } else {
1472 // If we still don't have a value for this attribute, try to find
1473 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1475 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001476 if (kDebugStyles) {
1477 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1478 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001479 newBlock = res.resolveReference(&value, block, &resid,
1480 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001481 if (kThrowOnBadId) {
1482 if (newBlock == BAD_INDEX) {
1483 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1484 return JNI_FALSE;
1485 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001486 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001487
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001488 if (newBlock >= 0) {
1489 block = newBlock;
1490 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001491
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001492 if (kDebugStyles) {
1493 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 }
1496 }
1497
1498 // Deal with the special @null value -- it turns back to TYPE_NULL.
1499 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001500 if (kDebugStyles) {
1501 ALOGI("-> Setting to @null!");
1502 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001504 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001505 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
1507
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001508 if (kDebugStyles) {
1509 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1510 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511
1512 // Write the final value back to Java.
1513 dest[STYLE_TYPE] = value.dataType;
1514 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001515 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1516 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 dest[STYLE_RESOURCE_ID] = resid;
1518 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001519 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1522 indicesIdx++;
1523 indices[indicesIdx] = ii;
1524 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 dest += STYLE_NUM_ENTRIES;
1527 }
1528
1529 res.unlock();
1530
1531 if (indices != NULL) {
1532 indices[0] = indicesIdx;
1533 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1534 }
1535 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1536 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1537
1538 return JNI_TRUE;
1539}
1540
1541static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001542 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 jintArray attrs,
1544 jintArray outValues,
1545 jintArray outIndices)
1546{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001547 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001548 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001549 return JNI_FALSE;
1550 }
1551 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001552 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001553 return JNI_FALSE;
1554 }
1555 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001556 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001557 return JNI_FALSE;
1558 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 AssetManager* am = assetManagerForJavaObject(env, clazz);
1561 if (am == NULL) {
1562 return JNI_FALSE;
1563 }
1564 const ResTable& res(am->getResources());
1565 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001566 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 const jsize NI = env->GetArrayLength(attrs);
1570 const jsize NV = env->GetArrayLength(outValues);
1571 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001572 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 return JNI_FALSE;
1574 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1577 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 return JNI_FALSE;
1579 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1582 jint* dest = baseDest;
1583 if (dest == NULL) {
1584 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 return JNI_FALSE;
1586 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 jint* indices = NULL;
1589 int indicesIdx = 0;
1590 if (outIndices != NULL) {
1591 if (env->GetArrayLength(outIndices) > NI) {
1592 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1593 }
1594 }
1595
1596 // Now lock down the resource object and start pulling stuff from it.
1597 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 // Retrieve the XML attributes, if requested.
1600 const jsize NX = xmlParser->getAttributeCount();
1601 jsize ix=0;
1602 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 // Now iterate through all of the attributes that the client has requested,
1607 // filling in each with whatever data we can find.
1608 ssize_t block = 0;
1609 uint32_t typeSetFlags;
1610 for (jsize ii=0; ii<NI; ii++) {
1611 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 // Try to find a value for this attribute...
1614 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001615 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001617 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001620 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 ix++;
1622 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1623 }
1624 // Retrieve the current XML attribute if it matches, and step to next.
1625 if (ix < NX && curIdent == curXmlAttr) {
1626 block = kXmlBlock;
1627 xmlParser->getAttributeValue(ix, &value);
1628 ix++;
1629 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1630 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1633 uint32_t resid = 0;
1634 if (value.dataType != Res_value::TYPE_NULL) {
1635 // Take care of resolving the found resource to its final value.
1636 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001637 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1638 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001639 if (kThrowOnBadId) {
1640 if (newBlock == BAD_INDEX) {
1641 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1642 return JNI_FALSE;
1643 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 if (newBlock >= 0) block = newBlock;
1646 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 // Deal with the special @null value -- it turns back to TYPE_NULL.
1649 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1650 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001651 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 // Write the final value back to Java.
1657 dest[STYLE_TYPE] = value.dataType;
1658 dest[STYLE_DATA] = value.data;
1659 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001660 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 dest[STYLE_RESOURCE_ID] = resid;
1662 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001663 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1666 indicesIdx++;
1667 indices[indicesIdx] = ii;
1668 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 dest += STYLE_NUM_ENTRIES;
1671 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 if (indices != NULL) {
1676 indices[0] = indicesIdx;
1677 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1678 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1681 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 return JNI_TRUE;
1684}
1685
1686static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1687 jint id)
1688{
1689 AssetManager* am = assetManagerForJavaObject(env, clazz);
1690 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001691 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
1693 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 res.lock();
1696 const ResTable::bag_entry* defStyleEnt = NULL;
1697 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1698 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001699
Ashok Bhat896043d2014-01-17 16:02:38 +00001700 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701}
1702
1703static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1704 jint id,
1705 jintArray outValues)
1706{
1707 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001708 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 return JNI_FALSE;
1710 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 AssetManager* am = assetManagerForJavaObject(env, clazz);
1713 if (am == NULL) {
1714 return JNI_FALSE;
1715 }
1716 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001717 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 Res_value value;
1719 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001721 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1724 jint* dest = baseDest;
1725 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001726 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 return JNI_FALSE;
1728 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 // Now lock down the resource object and start pulling stuff from it.
1731 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 const ResTable::bag_entry* arrayEnt = NULL;
1734 uint32_t arrayTypeSetFlags = 0;
1735 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1736 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1737 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 int i = 0;
1740 uint32_t typeSetFlags;
1741 while (i < NV && arrayEnt < endArrayEnt) {
1742 block = arrayEnt->stringBlock;
1743 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001744 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 uint32_t resid = 0;
1748 if (value.dataType != Res_value::TYPE_NULL) {
1749 // Take care of resolving the found resource to its final value.
1750 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001751 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1752 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001753 if (kThrowOnBadId) {
1754 if (newBlock == BAD_INDEX) {
1755 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1756 return JNI_FALSE;
1757 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 if (newBlock >= 0) block = newBlock;
1760 }
1761
1762 // Deal with the special @null value -- it turns back to TYPE_NULL.
1763 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1764 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001765 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 }
1767
1768 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1769
1770 // Write the final value back to Java.
1771 dest[STYLE_TYPE] = value.dataType;
1772 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001773 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 dest[STYLE_RESOURCE_ID] = resid;
1775 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001776 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 dest += STYLE_NUM_ENTRIES;
1778 i+= STYLE_NUM_ENTRIES;
1779 arrayEnt++;
1780 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 return i;
1789}
1790
Ashok Bhat896043d2014-01-17 16:02:38 +00001791static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 jint cookie,
1793 jstring fileName)
1794{
1795 AssetManager* am = assetManagerForJavaObject(env, clazz);
1796 if (am == NULL) {
1797 return 0;
1798 }
1799
Steve Block71f2cf12011-10-20 11:56:00 +01001800 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801
Elliott Hughes69a017b2011-04-08 14:10:28 -07001802 ScopedUtfChars fileName8(env, fileName);
1803 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 return 0;
1805 }
1806
Adam Lesinskide898ff2014-01-29 18:20:45 -08001807 int32_t assetCookie = static_cast<int32_t>(cookie);
1808 Asset* a = assetCookie
1809 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1810 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811
1812 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001813 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 return 0;
1815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816
Adam Lesinskide898ff2014-01-29 18:20:45 -08001817 const DynamicRefTable* dynamicRefTable =
1818 am->getResources().getDynamicRefTableForCookie(assetCookie);
1819 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1821 a->close();
1822 delete a;
1823
1824 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001825 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 return 0;
1827 }
1828
Ashok Bhat896043d2014-01-17 16:02:38 +00001829 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830}
1831
1832static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1833 jint arrayResId)
1834{
1835 AssetManager* am = assetManagerForJavaObject(env, clazz);
1836 if (am == NULL) {
1837 return NULL;
1838 }
1839 const ResTable& res(am->getResources());
1840
1841 const ResTable::bag_entry* startOfBag;
1842 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1843 if (N < 0) {
1844 return NULL;
1845 }
1846
1847 jintArray array = env->NewIntArray(N * 2);
1848 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 res.unlockBag(startOfBag);
1850 return NULL;
1851 }
1852
1853 Res_value value;
1854 const ResTable::bag_entry* bag = startOfBag;
1855 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1856 jint stringIndex = -1;
1857 jint stringBlock = 0;
1858 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 // Take care of resolving the found resource to its final value.
1861 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1862 if (value.dataType == Res_value::TYPE_STRING) {
1863 stringIndex = value.data;
1864 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001865
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001866 if (kThrowOnBadId) {
1867 if (stringBlock == BAD_INDEX) {
1868 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1869 return array;
1870 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001871 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 //todo: It might be faster to allocate a C array to contain
1874 // the blocknums and indices, put them in there and then
1875 // do just one SetIntArrayRegion()
1876 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1877 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1878 j = j + 2;
1879 }
1880 res.unlockBag(startOfBag);
1881 return array;
1882}
1883
1884static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1885 jint arrayResId)
1886{
1887 AssetManager* am = assetManagerForJavaObject(env, clazz);
1888 if (am == NULL) {
1889 return NULL;
1890 }
1891 const ResTable& res(am->getResources());
1892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 const ResTable::bag_entry* startOfBag;
1894 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1895 if (N < 0) {
1896 return NULL;
1897 }
1898
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001899 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001900 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 res.unlockBag(startOfBag);
1902 return NULL;
1903 }
1904
1905 Res_value value;
1906 const ResTable::bag_entry* bag = startOfBag;
1907 size_t strLen = 0;
1908 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1909 value = bag->map.value;
1910 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 // Take care of resolving the found resource to its final value.
1913 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001914 if (kThrowOnBadId) {
1915 if (block == BAD_INDEX) {
1916 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1917 return array;
1918 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001921 const ResStringPool* pool = res.getTableStringBlock(block);
1922 const char* str8 = pool->string8At(value.data, &strLen);
1923 if (str8 != NULL) {
1924 str = env->NewStringUTF(str8);
1925 } else {
1926 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001927 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1928 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001929 }
1930
1931 // If one of our NewString{UTF} calls failed due to memory, an
1932 // exception will be pending.
1933 if (env->ExceptionCheck()) {
1934 res.unlockBag(startOfBag);
1935 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 }
Kenny Root780d2a12010-02-22 22:36:26 -08001937
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001938 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001939
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001940 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1941 // If we have a large amount of strings in our array, we might
1942 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001943 env->DeleteLocalRef(str);
1944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 }
1946 res.unlockBag(startOfBag);
1947 return array;
1948}
1949
1950static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1951 jint arrayResId)
1952{
1953 AssetManager* am = assetManagerForJavaObject(env, clazz);
1954 if (am == NULL) {
1955 return NULL;
1956 }
1957 const ResTable& res(am->getResources());
1958
1959 const ResTable::bag_entry* startOfBag;
1960 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1961 if (N < 0) {
1962 return NULL;
1963 }
1964
1965 jintArray array = env->NewIntArray(N);
1966 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967 res.unlockBag(startOfBag);
1968 return NULL;
1969 }
1970
1971 Res_value value;
1972 const ResTable::bag_entry* bag = startOfBag;
1973 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1974 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 // Take care of resolving the found resource to its final value.
1977 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001978 if (kThrowOnBadId) {
1979 if (block == BAD_INDEX) {
1980 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1981 return array;
1982 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 if (value.dataType >= Res_value::TYPE_FIRST_INT
1985 && value.dataType <= Res_value::TYPE_LAST_INT) {
1986 int intVal = value.data;
1987 env->SetIntArrayRegion(array, i, 1, &intVal);
1988 }
1989 }
1990 res.unlockBag(startOfBag);
1991 return array;
1992}
1993
Jon Miranda042ad632014-09-03 17:57:35 -07001994static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1995 jint styleId)
1996{
1997 AssetManager* am = assetManagerForJavaObject(env, clazz);
1998 if (am == NULL) {
1999 return NULL;
2000 }
2001 const ResTable& res(am->getResources());
2002
2003 const ResTable::bag_entry* startOfBag;
2004 const ssize_t N = res.lockBag(styleId, &startOfBag);
2005 if (N < 0) {
2006 return NULL;
2007 }
2008
2009 jintArray array = env->NewIntArray(N);
2010 if (array == NULL) {
2011 res.unlockBag(startOfBag);
2012 return NULL;
2013 }
2014
Jon Miranda042ad632014-09-03 17:57:35 -07002015 const ResTable::bag_entry* bag = startOfBag;
2016 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2017 int resourceId = bag->map.name.ident;
2018 env->SetIntArrayRegion(array, i, 1, &resourceId);
2019 }
2020 res.unlockBag(startOfBag);
2021 return array;
2022}
2023
Mårten Kongstad48d22322014-01-31 14:43:27 +01002024static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002026 if (isSystem) {
2027 verifySystemIdmaps();
2028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 AssetManager* am = new AssetManager();
2030 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002031 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 return;
2033 }
2034
2035 am->addDefaultAssets();
2036
Steve Block71f2cf12011-10-20 11:56:00 +01002037 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002038 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039}
2040
2041static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2042{
2043 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002044 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002045 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 if (am != NULL) {
2047 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002048 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 }
2050}
2051
2052static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2053{
2054 return Asset::getGlobalCount();
2055}
2056
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002057static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2058{
2059 String8 alloc = Asset::getAssetAllocations();
2060 if (alloc.length() <= 0) {
2061 return NULL;
2062 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002063
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002064 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002065 return str;
2066}
2067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2069{
2070 return AssetManager::getGlobalCount();
2071}
2072
2073// ----------------------------------------------------------------------------
2074
2075/*
2076 * JNI registration.
2077 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002078static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 /* name, signature, funcPtr */
2080
2081 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002082 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_openAsset },
2084 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2085 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002086 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 (void*) android_content_AssetManager_openNonAssetNative },
2088 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2089 (void*) android_content_AssetManager_openNonAssetFdNative },
2090 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2091 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002092 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002094 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002096 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002098 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002100 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002102 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002104 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002106 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002107 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 { "isUpToDate", "()Z",
2109 (void*) android_content_AssetManager_isUpToDate },
2110
2111 // Resources.
2112 { "setLocale", "(Ljava/lang/String;)V",
2113 (void*) android_content_AssetManager_setLocale },
2114 { "getLocales", "()[Ljava/lang/String;",
2115 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002116 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 (void*) android_content_AssetManager_setConfiguration },
2118 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2119 (void*) android_content_AssetManager_getResourceIdentifier },
2120 { "getResourceName","(I)Ljava/lang/String;",
2121 (void*) android_content_AssetManager_getResourceName },
2122 { "getResourcePackageName","(I)Ljava/lang/String;",
2123 (void*) android_content_AssetManager_getResourcePackageName },
2124 { "getResourceTypeName","(I)Ljava/lang/String;",
2125 (void*) android_content_AssetManager_getResourceTypeName },
2126 { "getResourceEntryName","(I)Ljava/lang/String;",
2127 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002128 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 (void*) android_content_AssetManager_loadResourceValue },
2130 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2131 (void*) android_content_AssetManager_loadResourceBagValue },
2132 { "getStringBlockCount","()I",
2133 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002134 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 (void*) android_content_AssetManager_getNativeStringBlock },
2136 { "getCookieName","(I)Ljava/lang/String;",
2137 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002138 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2139 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140
2141 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002142 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002144 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002145 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002146 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002148 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002149 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002150 { "clearTheme", "(J)V",
2151 (void*) android_content_AssetManager_clearTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002152 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 (void*) android_content_AssetManager_loadThemeAttributeValue },
Alan Viverettec1d52792015-05-05 09:49:03 -07002154 { "getThemeChangingConfigurations", "(J)I",
2155 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002156 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002158 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002160 { "resolveAttrs","(JII[I[I[I[I)Z",
2161 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002162 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 (void*) android_content_AssetManager_retrieveAttributes },
2164 { "getArraySize","(I)I",
2165 (void*) android_content_AssetManager_getArraySize },
2166 { "retrieveArray","(I[I)I",
2167 (void*) android_content_AssetManager_retrieveArray },
2168
2169 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002170 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 (void*) android_content_AssetManager_openXmlAssetNative },
2172
2173 // Arrays.
2174 { "getArrayStringResource","(I)[Ljava/lang/String;",
2175 (void*) android_content_AssetManager_getArrayStringResource },
2176 { "getArrayStringInfo","(I)[I",
2177 (void*) android_content_AssetManager_getArrayStringInfo },
2178 { "getArrayIntResource","(I)[I",
2179 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002180 { "getStyleAttributes","(I)[I",
2181 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182
2183 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002184 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 (void*) android_content_AssetManager_init },
2186 { "destroy", "()V",
2187 (void*) android_content_AssetManager_destroy },
2188 { "getGlobalAssetCount", "()I",
2189 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002190 { "getAssetAllocations", "()Ljava/lang/String;",
2191 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002193 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194};
2195
2196int register_android_content_AssetManager(JNIEnv* env)
2197{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002198 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2199 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2200 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2201 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2202 "Ljava/lang/CharSequence;");
2203 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2204 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2205 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2206 "changingConfigurations", "I");
2207 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208
Andreas Gampe987f79f2014-11-18 17:29:46 -08002209 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2210 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2211 "Landroid/os/ParcelFileDescriptor;");
2212 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2213 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214
Andreas Gampe987f79f2014-11-18 17:29:46 -08002215 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2216 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002217
Andreas Gampe987f79f2014-11-18 17:29:46 -08002218 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2219 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220
Andreas Gampe987f79f2014-11-18 17:29:46 -08002221 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2222 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2223 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2224 "<init>", "()V");
2225 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2226 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002227
Andreas Gampe987f79f2014-11-18 17:29:46 -08002228 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2229 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230}
2231
2232}; // namespace android