blob: 3473d9dab732fc49189c4bb96a977be16158e976 [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
Filip Gruszczynski23493322015-07-29 17:02:59 -070086static struct configuration_offsets_t
87{
88 jclass classObject;
89 jmethodID constructor;
90 jfieldID mSmallestScreenWidthDpOffset;
91 jfieldID mScreenWidthDpOffset;
92 jfieldID mScreenHeightDpOffset;
93} gConfigurationOffsets;
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095jclass g_stringClass = NULL;
96
97// ----------------------------------------------------------------------------
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700100 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 STYLE_TYPE = 0,
102 STYLE_DATA = 1,
103 STYLE_ASSET_COOKIE = 2,
104 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700105 STYLE_CHANGING_CONFIGURATIONS = 4,
106 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107};
108
109static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
110 const Res_value& value, uint32_t ref, ssize_t block,
111 uint32_t typeSpecFlags, ResTable_config* config = NULL);
112
113jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
114 const Res_value& value, uint32_t ref, ssize_t block,
115 uint32_t typeSpecFlags, ResTable_config* config)
116{
117 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
118 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000119 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
121 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
122 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
123 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
124 typeSpecFlags);
125 if (config != NULL) {
126 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
127 }
128 return block;
129}
130
Mårten Kongstad48d22322014-01-31 14:43:27 +0100131// This is called by zygote (running as user root) as part of preloadResources.
132static void verifySystemIdmaps()
133{
134 pid_t pid;
135 char system_id[10];
136
137 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
138
139 switch (pid = fork()) {
140 case -1:
141 ALOGE("failed to fork for idmap: %s", strerror(errno));
142 break;
143 case 0: // child
144 {
145 struct __user_cap_header_struct capheader;
146 struct __user_cap_data_struct capdata;
147
148 memset(&capheader, 0, sizeof(capheader));
149 memset(&capdata, 0, sizeof(capdata));
150
151 capheader.version = _LINUX_CAPABILITY_VERSION;
152 capheader.pid = 0;
153
154 if (capget(&capheader, &capdata) != 0) {
155 ALOGE("capget: %s\n", strerror(errno));
156 exit(1);
157 }
158
159 capdata.effective = capdata.permitted;
160 if (capset(&capheader, &capdata) != 0) {
161 ALOGE("capset: %s\n", strerror(errno));
162 exit(1);
163 }
164
165 if (setgid(AID_SYSTEM) != 0) {
166 ALOGE("setgid: %s\n", strerror(errno));
167 exit(1);
168 }
169
170 if (setuid(AID_SYSTEM) != 0) {
171 ALOGE("setuid: %s\n", strerror(errno));
172 exit(1);
173 }
174
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100175 // Generic idmap parameters
176 const char* argv[7];
177 int argc = 0;
178 struct stat st;
179
180 memset(argv, NULL, sizeof(argv));
181 argv[argc++] = AssetManager::IDMAP_BIN;
182 argv[argc++] = "--scan";
183 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
184 argv[argc++] = AssetManager::TARGET_APK_PATH;
185 argv[argc++] = AssetManager::IDMAP_DIR;
186
187 // Directories to scan for overlays
188 // /vendor/overlay
189 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
190 argv[argc++] = AssetManager::OVERLAY_DIR;
191 }
192
193 // Finally, invoke idmap (if any overlay directory exists)
194 if (argc > 5) {
195 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
196 ALOGE("failed to execl for idmap: %s", strerror(errno));
197 exit(1); // should never get here
198 } else {
199 exit(0);
200 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100201 }
202 break;
203 default: // parent
204 waitpid(pid, NULL, 0);
205 break;
206 }
207}
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209// ----------------------------------------------------------------------------
210
211// this guy is exported to other jni routines
212AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
213{
Ashok Bhat896043d2014-01-17 16:02:38 +0000214 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
215 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 if (am != NULL) {
217 return am;
218 }
219 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
220 return NULL;
221}
222
Ashok Bhat896043d2014-01-17 16:02:38 +0000223static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 jstring fileName, jint mode)
225{
226 AssetManager* am = assetManagerForJavaObject(env, clazz);
227 if (am == NULL) {
228 return 0;
229 }
230
Steve Block71f2cf12011-10-20 11:56:00 +0100231 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
Elliott Hughes69a017b2011-04-08 14:10:28 -0700233 ScopedUtfChars fileName8(env, fileName);
234 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000235 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 return -1;
237 }
238
239 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
240 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700241 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 return -1;
243 }
244
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246
247 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700248 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 return -1;
250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251
252 //printf("Created Asset Stream: %p\n", a);
253
Ashok Bhat896043d2014-01-17 16:02:38 +0000254 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255}
256
257static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
258{
Kenny Rootddb76c42010-11-24 12:56:06 -0800259 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 int fd = a->openFileDescriptor(&startOffset, &length);
261 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700264 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 "This file can not be opened as a file descriptor; it is probably compressed");
266 return NULL;
267 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
270 if (offsets == NULL) {
271 close(fd);
272 return NULL;
273 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 offsets[0] = startOffset;
276 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700279
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700280 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 if (fileDesc == NULL) {
282 close(fd);
283 return NULL;
284 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 return newParcelFileDescriptor(env, fileDesc);
287}
288
289static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
290 jstring fileName, jlongArray outOffsets)
291{
292 AssetManager* am = assetManagerForJavaObject(env, clazz);
293 if (am == NULL) {
294 return NULL;
295 }
296
Steve Block71f2cf12011-10-20 11:56:00 +0100297 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298
Elliott Hughes69a017b2011-04-08 14:10:28 -0700299 ScopedUtfChars fileName8(env, fileName);
300 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 return NULL;
302 }
303
Elliott Hughes69a017b2011-04-08 14:10:28 -0700304 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700307 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 return NULL;
309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 //printf("Created Asset Stream: %p\n", a);
312
313 return returnParcelFileDescriptor(env, a, outOffsets);
314}
315
Ashok Bhat896043d2014-01-17 16:02:38 +0000316static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 jint cookie,
318 jstring fileName,
319 jint mode)
320{
321 AssetManager* am = assetManagerForJavaObject(env, clazz);
322 if (am == NULL) {
323 return 0;
324 }
325
Steve Block71f2cf12011-10-20 11:56:00 +0100326 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327
Elliott Hughes69a017b2011-04-08 14:10:28 -0700328 ScopedUtfChars fileName8(env, fileName);
329 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 return -1;
331 }
332
333 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
334 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700335 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 return -1;
337 }
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000340 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
341 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700342 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
344 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700345 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return -1;
347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348
349 //printf("Created Asset Stream: %p\n", a);
350
Ashok Bhat896043d2014-01-17 16:02:38 +0000351 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352}
353
354static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
355 jint cookie,
356 jstring fileName,
357 jlongArray outOffsets)
358{
359 AssetManager* am = assetManagerForJavaObject(env, clazz);
360 if (am == NULL) {
361 return NULL;
362 }
363
Steve Block71f2cf12011-10-20 11:56:00 +0100364 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
Elliott Hughes69a017b2011-04-08 14:10:28 -0700366 ScopedUtfChars fileName8(env, fileName);
367 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 return NULL;
369 }
370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000372 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700373 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374
375 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700376 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 return NULL;
378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379
380 //printf("Created Asset Stream: %p\n", a);
381
382 return returnParcelFileDescriptor(env, a, outOffsets);
383}
384
385static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
386 jstring fileName)
387{
388 AssetManager* am = assetManagerForJavaObject(env, clazz);
389 if (am == NULL) {
390 return NULL;
391 }
392
Elliott Hughes69a017b2011-04-08 14:10:28 -0700393 ScopedUtfChars fileName8(env, fileName);
394 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 return NULL;
396 }
397
Elliott Hughes69a017b2011-04-08 14:10:28 -0700398 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399
400 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700401 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 return NULL;
403 }
404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 size_t N = dir->getFileCount();
406
407 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100408 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 delete dir;
411 return NULL;
412 }
413
414 for (size_t i=0; i<N; i++) {
415 const String8& name = dir->getFileName(i);
416 jstring str = env->NewStringUTF(name.string());
417 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 delete dir;
419 return NULL;
420 }
421 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700422 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 }
424
425 delete dir;
426
427 return array;
428}
429
430static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000431 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432{
Ashok Bhat896043d2014-01-17 16:02:38 +0000433 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434
435 //printf("Destroying Asset Stream: %p\n", a);
436
437 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700438 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 return;
440 }
441
442 delete a;
443}
444
445static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000446 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447{
Ashok Bhat896043d2014-01-17 16:02:38 +0000448 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
450 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700451 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 return -1;
453 }
454
455 uint8_t b;
456 ssize_t res = a->read(&b, 1);
457 return res == 1 ? b : -1;
458}
459
460static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000461 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 jint off, jint len)
463{
Ashok Bhat896043d2014-01-17 16:02:38 +0000464 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465
466 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700467 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 return -1;
469 }
470
471 if (len == 0) {
472 return 0;
473 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 jsize bLen = env->GetArrayLength(bArray);
476 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700477 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 return -1;
479 }
480
481 jbyte* b = env->GetByteArrayElements(bArray, NULL);
482 ssize_t res = a->read(b+off, len);
483 env->ReleaseByteArrayElements(bArray, b, 0);
484
Ashok Bhat896043d2014-01-17 16:02:38 +0000485 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486
487 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700488 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 }
490 return -1;
491}
492
493static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000494 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 jlong offset, jint whence)
496{
Ashok Bhat896043d2014-01-17 16:02:38 +0000497 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498
499 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700500 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 return -1;
502 }
503
504 return a->seek(
505 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
506}
507
508static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000509 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510{
Ashok Bhat896043d2014-01-17 16:02:38 +0000511 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512
513 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700514 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 return -1;
516 }
517
518 return a->getLength();
519}
520
521static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000522 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523{
Ashok Bhat896043d2014-01-17 16:02:38 +0000524 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525
526 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700527 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 return -1;
529 }
530
531 return a->getRemainingLength();
532}
533
534static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
Tao Baia6d7e3f2015-09-01 18:49:54 -0700535 jstring path, jboolean appAsLib)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700537 ScopedUtfChars path8(env, path);
538 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800539 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 }
541
542 AssetManager* am = assetManagerForJavaObject(env, clazz);
543 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800544 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000547 int32_t cookie;
Tao Baia6d7e3f2015-09-01 18:49:54 -0700548 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000550 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551}
552
Mårten Kongstad48d22322014-01-31 14:43:27 +0100553static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
554 jstring idmapPath)
555{
556 ScopedUtfChars idmapPath8(env, idmapPath);
557 if (idmapPath8.c_str() == NULL) {
558 return 0;
559 }
560
561 AssetManager* am = assetManagerForJavaObject(env, clazz);
562 if (am == NULL) {
563 return 0;
564 }
565
566 int32_t cookie;
567 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
568
569 return (res) ? (jint)cookie : 0;
570}
571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
573{
574 AssetManager* am = assetManagerForJavaObject(env, clazz);
575 if (am == NULL) {
576 return JNI_TRUE;
577 }
578 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
579}
580
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800581static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582{
583 Vector<String8> locales;
584
585 AssetManager* am = assetManagerForJavaObject(env, clazz);
586 if (am == NULL) {
587 return NULL;
588 }
589
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800590 am->getLocales(&locales, includeSystemLocales);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591
592 const int N = locales.size();
593
594 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
595 if (result == NULL) {
596 return NULL;
597 }
598
599 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700600 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700601 if (str == NULL) {
602 return NULL;
603 }
604 env->SetObjectArrayElement(result, i, str);
605 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 }
607
608 return result;
609}
610
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800611static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
612{
613 return getLocales(env, clazz, true /* include system locales */);
614}
615
616static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
617{
618 return getLocales(env, clazz, false /* don't include system locales */);
619}
620
Filip Gruszczynski23493322015-07-29 17:02:59 -0700621static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
622 jobject result = env->NewObject(gConfigurationOffsets.classObject,
623 gConfigurationOffsets.constructor);
624 if (result == NULL) {
625 return NULL;
626 }
627
628 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
629 config.smallestScreenWidthDp);
630 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
631 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
632
633 return result;
634}
635
636static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
637 const Vector<ResTable_config>& configs) {
638 const int N = configs.size();
639 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
640 if (result == NULL) {
641 return NULL;
642 }
643
644 for (int i=0; i<N; i++) {
645 jobject config = constructConfigurationObject(env, configs[i]);
646 if (config == NULL) {
647 env->DeleteLocalRef(result);
648 return NULL;
649 }
650
651 env->SetObjectArrayElement(result, i, config);
652 env->DeleteLocalRef(config);
653 }
654
655 return result;
656}
657
658static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
659 AssetManager* am = assetManagerForJavaObject(env, clazz);
660 if (am == NULL) {
661 return NULL;
662 }
663
664 const ResTable& res(am->getResources());
665 Vector<ResTable_config> configs;
666 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
667
668 return getSizeConfigurationsInternal(env, configs);
669}
670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
672 jint mcc, jint mnc,
673 jstring locale, jint orientation,
674 jint touchscreen, jint density,
675 jint keyboard, jint keyboardHidden,
676 jint navigation,
677 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700678 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700679 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100680 jint screenLayout, jint uiMode,
681 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682{
683 AssetManager* am = assetManagerForJavaObject(env, clazz);
684 if (am == NULL) {
685 return;
686 }
687
688 ResTable_config config;
689 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700692
Adam Lesinski2738c962015-05-14 14:25:36 -0700693 // Constants duplicated from Java class android.content.res.Configuration.
694 static const jint kScreenLayoutRoundMask = 0x300;
695 static const jint kScreenLayoutRoundShift = 8;
696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 config.mcc = (uint16_t)mcc;
698 config.mnc = (uint16_t)mnc;
699 config.orientation = (uint8_t)orientation;
700 config.touchscreen = (uint8_t)touchscreen;
701 config.density = (uint16_t)density;
702 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700703 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 config.navigation = (uint8_t)navigation;
705 config.screenWidth = (uint16_t)screenWidth;
706 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700707 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700708 config.screenWidthDp = (uint16_t)screenWidthDp;
709 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700710 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100711 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 config.sdkVersion = (uint16_t)sdkVersion;
713 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700714
715 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
716 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
717 // into screenLayout2.
718 config.screenLayout2 =
719 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
720
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
724}
725
726static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
727 jstring name,
728 jstring defType,
729 jstring defPackage)
730{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700731 ScopedStringChars name16(env, name);
732 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 return 0;
734 }
735
736 AssetManager* am = assetManagerForJavaObject(env, clazz);
737 if (am == NULL) {
738 return 0;
739 }
740
Dan Albert66987492014-11-20 11:41:21 -0800741 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
742 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
743 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 jsize defTypeLen = defType
745 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800746 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
747 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
748 NULL))
749 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 jsize defPackageLen = defPackage
751 ? env->GetStringLength(defPackage) : 0;
752
753 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800754 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
755 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756
757 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800758 env->ReleaseStringChars(defPackage,
759 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 }
761 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800762 env->ReleaseStringChars(defType,
763 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765
766 return ident;
767}
768
769static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
770 jint resid)
771{
772 AssetManager* am = assetManagerForJavaObject(env, clazz);
773 if (am == NULL) {
774 return NULL;
775 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700778 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 return NULL;
780 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 String16 str;
783 if (name.package != NULL) {
784 str.setTo(name.package, name.packageLen);
785 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700786 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 if (str.size() > 0) {
788 char16_t div = ':';
789 str.append(&div, 1);
790 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700791 if (name.type8 != NULL) {
792 str.append(String16(name.type8, name.typeLen));
793 } else {
794 str.append(name.type, name.typeLen);
795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700797 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 if (str.size() > 0) {
799 char16_t div = '/';
800 str.append(&div, 1);
801 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700802 if (name.name8 != NULL) {
803 str.append(String16(name.name8, name.nameLen));
804 } else {
805 str.append(name.name, name.nameLen);
806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 return env->NewString((const jchar*)str.string(), str.size());
810}
811
812static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
813 jint resid)
814{
815 AssetManager* am = assetManagerForJavaObject(env, clazz);
816 if (am == NULL) {
817 return NULL;
818 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700821 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 return NULL;
823 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 if (name.package != NULL) {
826 return env->NewString((const jchar*)name.package, name.packageLen);
827 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 return NULL;
830}
831
832static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
833 jint resid)
834{
835 AssetManager* am = assetManagerForJavaObject(env, clazz);
836 if (am == NULL) {
837 return NULL;
838 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700841 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 return NULL;
843 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700844
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700845 if (name.type8 != NULL) {
846 return env->NewStringUTF(name.type8);
847 }
848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800849 if (name.type != NULL) {
850 return env->NewString((const jchar*)name.type, name.typeLen);
851 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 return NULL;
854}
855
856static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
857 jint resid)
858{
859 AssetManager* am = assetManagerForJavaObject(env, clazz);
860 if (am == NULL) {
861 return NULL;
862 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700865 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 return NULL;
867 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700868
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700869 if (name.name8 != NULL) {
870 return env->NewStringUTF(name.name8);
871 }
872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 if (name.name != NULL) {
874 return env->NewString((const jchar*)name.name, name.nameLen);
875 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 return NULL;
878}
879
880static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
881 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700882 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 jobject outValue,
884 jboolean resolve)
885{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800886 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800887 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700888 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800889 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 AssetManager* am = assetManagerForJavaObject(env, clazz);
891 if (am == NULL) {
892 return 0;
893 }
894 const ResTable& res(am->getResources());
895
896 Res_value value;
897 ResTable_config config;
898 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700899 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800900 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800901 if (block == BAD_INDEX) {
902 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
903 return 0;
904 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800905 }
906 uint32_t ref = ident;
907 if (resolve) {
908 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
909 if (kThrowOnBadId) {
910 if (block == BAD_INDEX) {
911 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
912 return 0;
913 }
914 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000916 if (block >= 0) {
917 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
918 }
919
920 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921}
922
923static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
924 jint ident, jint bagEntryId,
925 jobject outValue, jboolean resolve)
926{
927 AssetManager* am = assetManagerForJavaObject(env, clazz);
928 if (am == NULL) {
929 return 0;
930 }
931 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800933 // Now lock down the resource object and start pulling stuff from it.
934 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 ssize_t block = -1;
937 Res_value value;
938
939 const ResTable::bag_entry* entry = NULL;
940 uint32_t typeSpecFlags;
941 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
942
943 for (ssize_t i=0; i<entryCount; i++) {
944 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
945 block = entry->stringBlock;
946 value = entry->map.value;
947 }
948 entry++;
949 }
950
951 res.unlock();
952
953 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000954 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 uint32_t ref = ident;
958 if (resolve) {
959 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800960 if (kThrowOnBadId) {
961 if (block == BAD_INDEX) {
962 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
963 return 0;
964 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000967 if (block >= 0) {
968 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
969 }
970
971 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972}
973
974static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
975{
976 AssetManager* am = assetManagerForJavaObject(env, clazz);
977 if (am == NULL) {
978 return 0;
979 }
980 return am->getResources().getTableCount();
981}
982
Ashok Bhat896043d2014-01-17 16:02:38 +0000983static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 jint block)
985{
986 AssetManager* am = assetManagerForJavaObject(env, clazz);
987 if (am == NULL) {
988 return 0;
989 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000990 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991}
992
993static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
994 jint cookie)
995{
996 AssetManager* am = assetManagerForJavaObject(env, clazz);
997 if (am == NULL) {
998 return NULL;
999 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +00001000 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001002 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 return NULL;
1004 }
1005 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 return str;
1007}
1008
Adam Lesinskide898ff2014-01-29 18:20:45 -08001009static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1010{
1011 AssetManager* am = assetManagerForJavaObject(env, clazz);
1012 if (am == NULL) {
1013 return 0;
1014 }
1015
1016 const ResTable& res = am->getResources();
1017
1018 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1019 gSparseArrayOffsets.constructor);
1020 const size_t N = res.getBasePackageCount();
1021 for (size_t i = 0; i < N; i++) {
1022 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -08001023 env->CallVoidMethod(
1024 sparseArray, gSparseArrayOffsets.put,
1025 static_cast<jint>(res.getBasePackageId(i)),
1026 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1027 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -08001028 }
1029 return sparseArray;
1030}
1031
Ashok Bhat896043d2014-01-17 16:02:38 +00001032static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033{
1034 AssetManager* am = assetManagerForJavaObject(env, clazz);
1035 if (am == NULL) {
1036 return 0;
1037 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001038 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039}
1040
1041static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001042 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043{
Ashok Bhat896043d2014-01-17 16:02:38 +00001044 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 delete theme;
1046}
1047
1048static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001049 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 jint styleRes,
1051 jboolean force)
1052{
Ashok Bhat896043d2014-01-17 16:02:38 +00001053 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 theme->applyStyle(styleRes, force ? true : false);
1055}
1056
1057static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001058 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059{
Ashok Bhat896043d2014-01-17 16:02:38 +00001060 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1061 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 dest->setTo(*src);
1063}
1064
Alan Viverettee54d2452015-05-06 10:41:43 -07001065static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1066{
1067 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1068 theme->clear();
1069}
1070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001072 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073{
Ashok Bhat896043d2014-01-17 16:02:38 +00001074 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 const ResTable& res(theme->getResTable());
1076
1077 Res_value value;
1078 // XXX value could be different in different configs!
1079 uint32_t typeSpecFlags = 0;
1080 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1081 uint32_t ref = 0;
1082 if (resolve) {
1083 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001084 if (kThrowOnBadId) {
1085 if (block == BAD_INDEX) {
1086 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1087 return 0;
1088 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 }
1091 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1092}
1093
Alan Viverettec1d52792015-05-05 09:49:03 -07001094static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1095 jlong themeHandle)
1096{
1097 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1098 return theme->getChangingConfigurations();
1099}
1100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001102 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 jstring tag, jstring prefix)
1104{
Ashok Bhat896043d2014-01-17 16:02:38 +00001105 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001107 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 // XXX Need to use params.
1110 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111}
1112
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001113class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1114public:
1115 XmlAttributeFinder(const ResXMLParser* parser)
1116 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1117 , mParser(parser) {}
1118
1119 inline uint32_t getAttribute(jsize index) const {
1120 return mParser->getAttributeNameResID(index);
1121 }
1122
1123private:
1124 const ResXMLParser* mParser;
1125};
1126
1127class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1128public:
1129 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1130 : BackTrackingAttributeFinder(start, end) {}
1131
1132 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1133 return entry->map.name.ident;
1134 }
1135};
1136
Alan Viverette52b999f2014-03-24 18:00:26 -07001137static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1138 jlong themeToken,
1139 jint defStyleAttr,
1140 jint defStyleRes,
1141 jintArray inValues,
1142 jintArray attrs,
1143 jintArray outValues,
1144 jintArray outIndices)
1145{
1146 if (themeToken == 0) {
1147 jniThrowNullPointerException(env, "theme token");
1148 return JNI_FALSE;
1149 }
1150 if (attrs == NULL) {
1151 jniThrowNullPointerException(env, "attrs");
1152 return JNI_FALSE;
1153 }
1154 if (outValues == NULL) {
1155 jniThrowNullPointerException(env, "out values");
1156 return JNI_FALSE;
1157 }
1158
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001159 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001160 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1161 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001162 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001163
1164 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1165 const ResTable& res = theme->getResTable();
1166 ResTable_config config;
1167 Res_value value;
1168
1169 const jsize NI = env->GetArrayLength(attrs);
1170 const jsize NV = env->GetArrayLength(outValues);
1171 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1172 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1173 return JNI_FALSE;
1174 }
1175
1176 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1177 if (src == NULL) {
1178 return JNI_FALSE;
1179 }
1180
1181 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1182 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1183
1184 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1185 jint* dest = baseDest;
1186 if (dest == NULL) {
1187 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1188 return JNI_FALSE;
1189 }
1190
1191 jint* indices = NULL;
1192 int indicesIdx = 0;
1193 if (outIndices != NULL) {
1194 if (env->GetArrayLength(outIndices) > NI) {
1195 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1196 }
1197 }
1198
1199 // Load default style from attribute, if specified...
1200 uint32_t defStyleBagTypeSetFlags = 0;
1201 if (defStyleAttr != 0) {
1202 Res_value value;
1203 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1204 if (value.dataType == Res_value::TYPE_REFERENCE) {
1205 defStyleRes = value.data;
1206 }
1207 }
1208 }
1209
1210 // Now lock down the resource object and start pulling stuff from it.
1211 res.lock();
1212
1213 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001214 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001215 uint32_t defStyleTypeSetFlags = 0;
1216 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001217 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001218 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001219 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1220 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001221
1222 // Now iterate through all of the attributes that the client has requested,
1223 // filling in each with whatever data we can find.
1224 ssize_t block = 0;
1225 uint32_t typeSetFlags;
1226 for (jsize ii=0; ii<NI; ii++) {
1227 const uint32_t curIdent = (uint32_t)src[ii];
1228
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001229 if (kDebugStyles) {
1230 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1231 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001232
1233 // Try to find a value for this attribute... we prioritize values
1234 // coming from, first XML attributes, then XML style, then default
1235 // style, and finally the theme.
1236 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001237 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001238 typeSetFlags = 0;
1239 config.density = 0;
1240
1241 // Retrieve the current input value if available.
1242 if (NSV > 0 && srcValues[ii] != 0) {
1243 block = -1;
1244 value.dataType = Res_value::TYPE_ATTRIBUTE;
1245 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001246 if (kDebugStyles) {
1247 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1248 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001249 }
1250
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001251 if (value.dataType == Res_value::TYPE_NULL) {
1252 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1253 if (defStyleEntry != defStyleEnd) {
1254 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001255 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001256 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001257 if (kDebugStyles) {
1258 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1259 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001260 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001261 }
1262
1263 uint32_t resid = 0;
1264 if (value.dataType != Res_value::TYPE_NULL) {
1265 // Take care of resolving the found resource to its final value.
1266 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1267 &resid, &typeSetFlags, &config);
1268 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001269 if (kDebugStyles) {
1270 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1271 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001272 } else {
1273 // If we still don't have a value for this attribute, try to find
1274 // it in the theme!
1275 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1276 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001277 if (kDebugStyles) {
1278 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1279 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001280 newBlock = res.resolveReference(&value, block, &resid,
1281 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001282 if (kThrowOnBadId) {
1283 if (newBlock == BAD_INDEX) {
1284 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1285 return JNI_FALSE;
1286 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001287 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001288 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001289 if (kDebugStyles) {
1290 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1291 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001292 }
1293 }
1294
1295 // Deal with the special @null value -- it turns back to TYPE_NULL.
1296 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001297 if (kDebugStyles) {
1298 ALOGI("-> Setting to @null!");
1299 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001300 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001301 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001302 block = -1;
1303 }
1304
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001305 if (kDebugStyles) {
1306 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1307 value.data);
1308 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001309
1310 // Write the final value back to Java.
1311 dest[STYLE_TYPE] = value.dataType;
1312 dest[STYLE_DATA] = value.data;
1313 dest[STYLE_ASSET_COOKIE] =
1314 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1315 dest[STYLE_RESOURCE_ID] = resid;
1316 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1317 dest[STYLE_DENSITY] = config.density;
1318
1319 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1320 indicesIdx++;
1321 indices[indicesIdx] = ii;
1322 }
1323
1324 dest += STYLE_NUM_ENTRIES;
1325 }
1326
1327 res.unlock();
1328
1329 if (indices != NULL) {
1330 indices[0] = indicesIdx;
1331 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1332 }
1333 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1334 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1335 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1336
1337 return JNI_TRUE;
1338}
1339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001341 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 jint defStyleAttr,
1343 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001344 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 jintArray attrs,
1346 jintArray outValues,
1347 jintArray outIndices)
1348{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001349 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001350 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001351 return JNI_FALSE;
1352 }
1353 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001354 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001355 return JNI_FALSE;
1356 }
1357 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001358 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 return JNI_FALSE;
1360 }
1361
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001362 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001363 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1364 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1365 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001366 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001367
Ashok Bhat896043d2014-01-17 16:02:38 +00001368 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001370 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001371 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 Res_value value;
1373
1374 const jsize NI = env->GetArrayLength(attrs);
1375 const jsize NV = env->GetArrayLength(outValues);
1376 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001377 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 return JNI_FALSE;
1379 }
1380
1381 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1382 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 return JNI_FALSE;
1384 }
1385
1386 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1387 jint* dest = baseDest;
1388 if (dest == NULL) {
1389 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 return JNI_FALSE;
1391 }
1392
1393 jint* indices = NULL;
1394 int indicesIdx = 0;
1395 if (outIndices != NULL) {
1396 if (env->GetArrayLength(outIndices) > NI) {
1397 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1398 }
1399 }
1400
1401 // Load default style from attribute, if specified...
1402 uint32_t defStyleBagTypeSetFlags = 0;
1403 if (defStyleAttr != 0) {
1404 Res_value value;
1405 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1406 if (value.dataType == Res_value::TYPE_REFERENCE) {
1407 defStyleRes = value.data;
1408 }
1409 }
1410 }
1411
1412 // Retrieve the style class associated with the current XML tag.
1413 int style = 0;
1414 uint32_t styleBagTypeSetFlags = 0;
1415 if (xmlParser != NULL) {
1416 ssize_t idx = xmlParser->indexOfStyle();
1417 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1418 if (value.dataType == value.TYPE_ATTRIBUTE) {
1419 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1420 value.dataType = Res_value::TYPE_NULL;
1421 }
1422 }
1423 if (value.dataType == value.TYPE_REFERENCE) {
1424 style = value.data;
1425 }
1426 }
1427 }
1428
1429 // Now lock down the resource object and start pulling stuff from it.
1430 res.lock();
1431
1432 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001433 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 uint32_t defStyleTypeSetFlags = 0;
1435 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001436 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001438 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1439 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440
1441 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001442 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001444 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001446 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1447 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448
1449 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001451 XmlAttributeFinder xmlAttrFinder(xmlParser);
1452 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453
1454 // Now iterate through all of the attributes that the client has requested,
1455 // filling in each with whatever data we can find.
1456 ssize_t block = 0;
1457 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001458 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 const uint32_t curIdent = (uint32_t)src[ii];
1460
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001461 if (kDebugStyles) {
1462 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1463 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 // Try to find a value for this attribute... we prioritize values
1466 // coming from, first XML attributes, then XML style, then default
1467 // style, and finally the theme.
1468 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001469 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001471 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001473 // Walk through the xml attributes looking for the requested attribute.
1474 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1475 if (xmlAttrIdx != xmlAttrEnd) {
1476 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001478 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001479 if (kDebugStyles) {
1480 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 }
1483
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001484 if (value.dataType == Res_value::TYPE_NULL) {
1485 // Walk through the style class values looking for the requested attribute.
1486 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1487 if (styleAttrEntry != styleAttrEnd) {
1488 // We found the attribute we were looking for.
1489 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001491 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001492 if (kDebugStyles) {
1493 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 }
1497
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001498 if (value.dataType == Res_value::TYPE_NULL) {
1499 // Walk through the default style values looking for the requested attribute.
1500 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1501 if (defStyleAttrEntry != defStyleAttrEnd) {
1502 // We found the attribute we were looking for.
1503 block = defStyleAttrEntry->stringBlock;
1504 typeSetFlags = styleTypeSetFlags;
1505 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001506 if (kDebugStyles) {
1507 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 }
1511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 uint32_t resid = 0;
1513 if (value.dataType != Res_value::TYPE_NULL) {
1514 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001515 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1516 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001517 if (newBlock >= 0) {
1518 block = newBlock;
1519 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001520
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001521 if (kDebugStyles) {
1522 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1523 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 } else {
1525 // If we still don't have a value for this attribute, try to find
1526 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1528 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001529 if (kDebugStyles) {
1530 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1531 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001532 newBlock = res.resolveReference(&value, block, &resid,
1533 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001534 if (kThrowOnBadId) {
1535 if (newBlock == BAD_INDEX) {
1536 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1537 return JNI_FALSE;
1538 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001539 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001540
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001541 if (newBlock >= 0) {
1542 block = newBlock;
1543 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001544
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001545 if (kDebugStyles) {
1546 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1547 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 }
1549 }
1550
1551 // Deal with the special @null value -- it turns back to TYPE_NULL.
1552 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001553 if (kDebugStyles) {
1554 ALOGI("-> Setting to @null!");
1555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001557 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001558 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001561 if (kDebugStyles) {
1562 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564
1565 // Write the final value back to Java.
1566 dest[STYLE_TYPE] = value.dataType;
1567 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001568 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1569 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 dest[STYLE_RESOURCE_ID] = resid;
1571 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001572 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1575 indicesIdx++;
1576 indices[indicesIdx] = ii;
1577 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 dest += STYLE_NUM_ENTRIES;
1580 }
1581
1582 res.unlock();
1583
1584 if (indices != NULL) {
1585 indices[0] = indicesIdx;
1586 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1587 }
1588 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1589 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1590
1591 return JNI_TRUE;
1592}
1593
1594static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001595 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 jintArray attrs,
1597 jintArray outValues,
1598 jintArray outIndices)
1599{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001600 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001602 return JNI_FALSE;
1603 }
1604 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001605 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001606 return JNI_FALSE;
1607 }
1608 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001609 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 return JNI_FALSE;
1611 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 AssetManager* am = assetManagerForJavaObject(env, clazz);
1614 if (am == NULL) {
1615 return JNI_FALSE;
1616 }
1617 const ResTable& res(am->getResources());
1618 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001619 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 const jsize NI = env->GetArrayLength(attrs);
1623 const jsize NV = env->GetArrayLength(outValues);
1624 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001625 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 return JNI_FALSE;
1627 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1630 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 return JNI_FALSE;
1632 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1635 jint* dest = baseDest;
1636 if (dest == NULL) {
1637 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 return JNI_FALSE;
1639 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 jint* indices = NULL;
1642 int indicesIdx = 0;
1643 if (outIndices != NULL) {
1644 if (env->GetArrayLength(outIndices) > NI) {
1645 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1646 }
1647 }
1648
1649 // Now lock down the resource object and start pulling stuff from it.
1650 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 // Retrieve the XML attributes, if requested.
1653 const jsize NX = xmlParser->getAttributeCount();
1654 jsize ix=0;
1655 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 // Now iterate through all of the attributes that the client has requested,
1660 // filling in each with whatever data we can find.
1661 ssize_t block = 0;
1662 uint32_t typeSetFlags;
1663 for (jsize ii=0; ii<NI; ii++) {
1664 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 // Try to find a value for this attribute...
1667 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001668 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001670 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001673 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 ix++;
1675 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1676 }
1677 // Retrieve the current XML attribute if it matches, and step to next.
1678 if (ix < NX && curIdent == curXmlAttr) {
1679 block = kXmlBlock;
1680 xmlParser->getAttributeValue(ix, &value);
1681 ix++;
1682 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1683 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1686 uint32_t resid = 0;
1687 if (value.dataType != Res_value::TYPE_NULL) {
1688 // Take care of resolving the found resource to its final value.
1689 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001690 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1691 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001692 if (kThrowOnBadId) {
1693 if (newBlock == BAD_INDEX) {
1694 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1695 return JNI_FALSE;
1696 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 if (newBlock >= 0) block = newBlock;
1699 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 // Deal with the special @null value -- it turns back to TYPE_NULL.
1702 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1703 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001704 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 // Write the final value back to Java.
1710 dest[STYLE_TYPE] = value.dataType;
1711 dest[STYLE_DATA] = value.data;
1712 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001713 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714 dest[STYLE_RESOURCE_ID] = resid;
1715 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001716 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1719 indicesIdx++;
1720 indices[indicesIdx] = ii;
1721 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 dest += STYLE_NUM_ENTRIES;
1724 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 if (indices != NULL) {
1729 indices[0] = indicesIdx;
1730 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1731 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1734 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 return JNI_TRUE;
1737}
1738
1739static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1740 jint id)
1741{
1742 AssetManager* am = assetManagerForJavaObject(env, clazz);
1743 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001744 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 }
1746 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 res.lock();
1749 const ResTable::bag_entry* defStyleEnt = NULL;
1750 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1751 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001752
Ashok Bhat896043d2014-01-17 16:02:38 +00001753 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754}
1755
1756static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1757 jint id,
1758 jintArray outValues)
1759{
1760 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001761 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 return JNI_FALSE;
1763 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 AssetManager* am = assetManagerForJavaObject(env, clazz);
1766 if (am == NULL) {
1767 return JNI_FALSE;
1768 }
1769 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001770 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 Res_value value;
1772 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1777 jint* dest = baseDest;
1778 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001779 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 return JNI_FALSE;
1781 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 // Now lock down the resource object and start pulling stuff from it.
1784 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 const ResTable::bag_entry* arrayEnt = NULL;
1787 uint32_t arrayTypeSetFlags = 0;
1788 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1789 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1790 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 int i = 0;
1793 uint32_t typeSetFlags;
1794 while (i < NV && arrayEnt < endArrayEnt) {
1795 block = arrayEnt->stringBlock;
1796 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001797 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 uint32_t resid = 0;
1801 if (value.dataType != Res_value::TYPE_NULL) {
1802 // Take care of resolving the found resource to its final value.
1803 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001804 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1805 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001806 if (kThrowOnBadId) {
1807 if (newBlock == BAD_INDEX) {
1808 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1809 return JNI_FALSE;
1810 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 if (newBlock >= 0) block = newBlock;
1813 }
1814
1815 // Deal with the special @null value -- it turns back to TYPE_NULL.
1816 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1817 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001818 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001819 }
1820
1821 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1822
1823 // Write the final value back to Java.
1824 dest[STYLE_TYPE] = value.dataType;
1825 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001826 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 dest[STYLE_RESOURCE_ID] = resid;
1828 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001829 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 dest += STYLE_NUM_ENTRIES;
1831 i+= STYLE_NUM_ENTRIES;
1832 arrayEnt++;
1833 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 return i;
1842}
1843
Ashok Bhat896043d2014-01-17 16:02:38 +00001844static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 jint cookie,
1846 jstring fileName)
1847{
1848 AssetManager* am = assetManagerForJavaObject(env, clazz);
1849 if (am == NULL) {
1850 return 0;
1851 }
1852
Steve Block71f2cf12011-10-20 11:56:00 +01001853 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854
Elliott Hughes69a017b2011-04-08 14:10:28 -07001855 ScopedUtfChars fileName8(env, fileName);
1856 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return 0;
1858 }
1859
Adam Lesinskide898ff2014-01-29 18:20:45 -08001860 int32_t assetCookie = static_cast<int32_t>(cookie);
1861 Asset* a = assetCookie
1862 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1863 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864
1865 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001866 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 return 0;
1868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869
Adam Lesinskide898ff2014-01-29 18:20:45 -08001870 const DynamicRefTable* dynamicRefTable =
1871 am->getResources().getDynamicRefTableForCookie(assetCookie);
1872 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1874 a->close();
1875 delete a;
1876
1877 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001878 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 return 0;
1880 }
1881
Ashok Bhat896043d2014-01-17 16:02:38 +00001882 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883}
1884
1885static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1886 jint arrayResId)
1887{
1888 AssetManager* am = assetManagerForJavaObject(env, clazz);
1889 if (am == NULL) {
1890 return NULL;
1891 }
1892 const ResTable& res(am->getResources());
1893
1894 const ResTable::bag_entry* startOfBag;
1895 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1896 if (N < 0) {
1897 return NULL;
1898 }
1899
1900 jintArray array = env->NewIntArray(N * 2);
1901 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 res.unlockBag(startOfBag);
1903 return NULL;
1904 }
1905
1906 Res_value value;
1907 const ResTable::bag_entry* bag = startOfBag;
1908 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1909 jint stringIndex = -1;
1910 jint stringBlock = 0;
1911 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 // Take care of resolving the found resource to its final value.
1914 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1915 if (value.dataType == Res_value::TYPE_STRING) {
1916 stringIndex = value.data;
1917 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001918
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001919 if (kThrowOnBadId) {
1920 if (stringBlock == BAD_INDEX) {
1921 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1922 return array;
1923 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001924 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 //todo: It might be faster to allocate a C array to contain
1927 // the blocknums and indices, put them in there and then
1928 // do just one SetIntArrayRegion()
1929 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1930 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1931 j = j + 2;
1932 }
1933 res.unlockBag(startOfBag);
1934 return array;
1935}
1936
1937static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1938 jint arrayResId)
1939{
1940 AssetManager* am = assetManagerForJavaObject(env, clazz);
1941 if (am == NULL) {
1942 return NULL;
1943 }
1944 const ResTable& res(am->getResources());
1945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 const ResTable::bag_entry* startOfBag;
1947 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1948 if (N < 0) {
1949 return NULL;
1950 }
1951
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001952 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001953 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 res.unlockBag(startOfBag);
1955 return NULL;
1956 }
1957
1958 Res_value value;
1959 const ResTable::bag_entry* bag = startOfBag;
1960 size_t strLen = 0;
1961 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1962 value = bag->map.value;
1963 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 // Take care of resolving the found resource to its final value.
1966 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001967 if (kThrowOnBadId) {
1968 if (block == BAD_INDEX) {
1969 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1970 return array;
1971 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001972 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001974 const ResStringPool* pool = res.getTableStringBlock(block);
1975 const char* str8 = pool->string8At(value.data, &strLen);
1976 if (str8 != NULL) {
1977 str = env->NewStringUTF(str8);
1978 } else {
1979 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001980 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1981 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001982 }
1983
1984 // If one of our NewString{UTF} calls failed due to memory, an
1985 // exception will be pending.
1986 if (env->ExceptionCheck()) {
1987 res.unlockBag(startOfBag);
1988 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 }
Kenny Root780d2a12010-02-22 22:36:26 -08001990
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001991 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001992
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001993 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1994 // If we have a large amount of strings in our array, we might
1995 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001996 env->DeleteLocalRef(str);
1997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001998 }
1999 res.unlockBag(startOfBag);
2000 return array;
2001}
2002
2003static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
2004 jint arrayResId)
2005{
2006 AssetManager* am = assetManagerForJavaObject(env, clazz);
2007 if (am == NULL) {
2008 return NULL;
2009 }
2010 const ResTable& res(am->getResources());
2011
2012 const ResTable::bag_entry* startOfBag;
2013 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
2014 if (N < 0) {
2015 return NULL;
2016 }
2017
2018 jintArray array = env->NewIntArray(N);
2019 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 res.unlockBag(startOfBag);
2021 return NULL;
2022 }
2023
2024 Res_value value;
2025 const ResTable::bag_entry* bag = startOfBag;
2026 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2027 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07002028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 // Take care of resolving the found resource to its final value.
2030 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08002031 if (kThrowOnBadId) {
2032 if (block == BAD_INDEX) {
2033 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
2034 return array;
2035 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002036 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 if (value.dataType >= Res_value::TYPE_FIRST_INT
2038 && value.dataType <= Res_value::TYPE_LAST_INT) {
2039 int intVal = value.data;
2040 env->SetIntArrayRegion(array, i, 1, &intVal);
2041 }
2042 }
2043 res.unlockBag(startOfBag);
2044 return array;
2045}
2046
Jon Miranda042ad632014-09-03 17:57:35 -07002047static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
2048 jint styleId)
2049{
2050 AssetManager* am = assetManagerForJavaObject(env, clazz);
2051 if (am == NULL) {
2052 return NULL;
2053 }
2054 const ResTable& res(am->getResources());
2055
2056 const ResTable::bag_entry* startOfBag;
2057 const ssize_t N = res.lockBag(styleId, &startOfBag);
2058 if (N < 0) {
2059 return NULL;
2060 }
2061
2062 jintArray array = env->NewIntArray(N);
2063 if (array == NULL) {
2064 res.unlockBag(startOfBag);
2065 return NULL;
2066 }
2067
Jon Miranda042ad632014-09-03 17:57:35 -07002068 const ResTable::bag_entry* bag = startOfBag;
2069 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2070 int resourceId = bag->map.name.ident;
2071 env->SetIntArrayRegion(array, i, 1, &resourceId);
2072 }
2073 res.unlockBag(startOfBag);
2074 return array;
2075}
2076
Mårten Kongstad48d22322014-01-31 14:43:27 +01002077static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002079 if (isSystem) {
2080 verifySystemIdmaps();
2081 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 AssetManager* am = new AssetManager();
2083 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002084 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 return;
2086 }
2087
2088 am->addDefaultAssets();
2089
Steve Block71f2cf12011-10-20 11:56:00 +01002090 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002091 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092}
2093
2094static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2095{
2096 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002097 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002098 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 if (am != NULL) {
2100 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002101 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102 }
2103}
2104
2105static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2106{
2107 return Asset::getGlobalCount();
2108}
2109
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002110static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2111{
2112 String8 alloc = Asset::getAssetAllocations();
2113 if (alloc.length() <= 0) {
2114 return NULL;
2115 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002116
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002117 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002118 return str;
2119}
2120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2122{
2123 return AssetManager::getGlobalCount();
2124}
2125
2126// ----------------------------------------------------------------------------
2127
2128/*
2129 * JNI registration.
2130 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002131static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132 /* name, signature, funcPtr */
2133
2134 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002135 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 (void*) android_content_AssetManager_openAsset },
2137 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2138 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002139 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 (void*) android_content_AssetManager_openNonAssetNative },
2141 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2142 (void*) android_content_AssetManager_openNonAssetFdNative },
2143 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2144 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002145 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002147 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002149 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002151 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 (void*) android_content_AssetManager_seekAsset },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002153 { "getAssetLength", "!(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 (void*) android_content_AssetManager_getAssetLength },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002155 { "getAssetRemainingLength", "!(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 (void*) android_content_AssetManager_getAssetRemainingLength },
Tao Baia6d7e3f2015-09-01 18:49:54 -07002157 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002159 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002160 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 { "isUpToDate", "()Z",
2162 (void*) android_content_AssetManager_isUpToDate },
2163
2164 // Resources.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 { "getLocales", "()[Ljava/lang/String;",
2166 (void*) android_content_AssetManager_getLocales },
Roozbeh Pournader1c686f22015-12-18 14:22:14 -08002167 { "getNonSystemLocales", "()[Ljava/lang/String;",
2168 (void*) android_content_AssetManager_getNonSystemLocales },
Filip Gruszczynski23493322015-07-29 17:02:59 -07002169 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
2170 (void*) android_content_AssetManager_getSizeConfigurations },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002171 { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 (void*) android_content_AssetManager_setConfiguration },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002173 { "getResourceIdentifier","!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 (void*) android_content_AssetManager_getResourceIdentifier },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002175 { "getResourceName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 (void*) android_content_AssetManager_getResourceName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002177 { "getResourcePackageName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 (void*) android_content_AssetManager_getResourcePackageName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002179 { "getResourceTypeName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 (void*) android_content_AssetManager_getResourceTypeName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002181 { "getResourceEntryName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 (void*) android_content_AssetManager_getResourceEntryName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002183 { "loadResourceValue","!(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 (void*) android_content_AssetManager_loadResourceValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002185 { "loadResourceBagValue","!(IILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 (void*) android_content_AssetManager_loadResourceBagValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002187 { "getStringBlockCount","!()I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 (void*) android_content_AssetManager_getStringBlockCount },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002189 { "getNativeStringBlock","!(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 (void*) android_content_AssetManager_getNativeStringBlock },
2191 { "getCookieName","(I)Ljava/lang/String;",
2192 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002193 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2194 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195
2196 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002197 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002199 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002201 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002203 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002205 { "clearTheme", "(J)V",
2206 (void*) android_content_AssetManager_clearTheme },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002207 { "loadThemeAttributeValue", "!(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 (void*) android_content_AssetManager_loadThemeAttributeValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002209 { "getThemeChangingConfigurations", "!(J)I",
Alan Viverettec1d52792015-05-05 09:49:03 -07002210 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002211 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 (void*) android_content_AssetManager_dumpTheme },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002213 { "applyStyle","!(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 (void*) android_content_AssetManager_applyStyle },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002215 { "resolveAttrs","!(JII[I[I[I[I)Z",
Alan Viverette607bd842014-09-12 12:36:35 -07002216 (void*) android_content_AssetManager_resolveAttrs },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002217 { "retrieveAttributes","!(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 (void*) android_content_AssetManager_retrieveAttributes },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002219 { "getArraySize","!(I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 (void*) android_content_AssetManager_getArraySize },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002221 { "retrieveArray","!(I[I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 (void*) android_content_AssetManager_retrieveArray },
2223
2224 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002225 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002226 (void*) android_content_AssetManager_openXmlAssetNative },
2227
2228 // Arrays.
2229 { "getArrayStringResource","(I)[Ljava/lang/String;",
2230 (void*) android_content_AssetManager_getArrayStringResource },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002231 { "getArrayStringInfo","!(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 (void*) android_content_AssetManager_getArrayStringInfo },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002233 { "getArrayIntResource","!(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 (void*) android_content_AssetManager_getArrayIntResource },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002235 { "getStyleAttributes","!(I)[I",
Jon Miranda042ad632014-09-03 17:57:35 -07002236 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237
2238 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002239 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 (void*) android_content_AssetManager_init },
2241 { "destroy", "()V",
2242 (void*) android_content_AssetManager_destroy },
2243 { "getGlobalAssetCount", "()I",
2244 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002245 { "getAssetAllocations", "()Ljava/lang/String;",
2246 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002248 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249};
2250
2251int register_android_content_AssetManager(JNIEnv* env)
2252{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002253 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2254 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2255 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2256 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2257 "Ljava/lang/CharSequence;");
2258 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2259 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2260 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2261 "changingConfigurations", "I");
2262 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263
Andreas Gampe987f79f2014-11-18 17:29:46 -08002264 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2265 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2266 "Landroid/os/ParcelFileDescriptor;");
2267 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2268 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269
Andreas Gampe987f79f2014-11-18 17:29:46 -08002270 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2271 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272
Andreas Gampe987f79f2014-11-18 17:29:46 -08002273 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2274 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002275
Andreas Gampe987f79f2014-11-18 17:29:46 -08002276 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2277 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2278 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2279 "<init>", "()V");
2280 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2281 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002282
Filip Gruszczynski23493322015-07-29 17:02:59 -07002283 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
2284 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
2285 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
2286 "<init>", "()V");
2287 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2288 "smallestScreenWidthDp", "I");
2289 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2290 "screenWidthDp", "I");
2291 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
2292 "screenHeightDp", "I");
2293
Andreas Gampe987f79f2014-11-18 17:29:46 -08002294 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2295 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296}
2297
2298}; // namespace android