blob: ef32afee24ea7dffc941e6694acac76ae58ce0de [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>
Jakub Adamek1c15c632016-09-23 09:07:11 +010028#include <sys/system_properties.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010029
Dan Albert46d84442014-11-18 16:07:51 -080030#include <private/android_filesystem_config.h> // for AID_SYSTEM
31
Dan Albert3a091b72014-11-20 15:41:25 -080032#include "androidfw/Asset.h"
33#include "androidfw/AssetManager.h"
34#include "androidfw/AttributeFinder.h"
35#include "androidfw/ResourceTypes.h"
36#include "android_runtime/AndroidRuntime.h"
37#include "android_util_Binder.h"
38#include "core_jni_helpers.h"
39#include "jni.h"
Dan Albert46d84442014-11-18 16:07:51 -080040#include "JNIHelp.h"
41#include "ScopedStringChars.h"
42#include "ScopedUtfChars.h"
Dan Albert46d84442014-11-18 16:07:51 -080043#include "utils/Log.h"
44#include "utils/misc.h"
Jakub Adamek1c15c632016-09-23 09:07:11 +010045#include "utils/String8.h"
Dan Albert46d84442014-11-18 16:07:51 -080046
Mårten Kongstad48d22322014-01-31 14:43:27 +010047extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
48extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
51namespace android {
52
Andreas Gampe0f0b4912014-11-12 08:03:48 -080053static const bool kThrowOnBadId = false;
54static const bool kDebugStyles = false;
55
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080056// ----------------------------------------------------------------------------
57
58static struct typedvalue_offsets_t
59{
60 jfieldID mType;
61 jfieldID mData;
62 jfieldID mString;
63 jfieldID mAssetCookie;
64 jfieldID mResourceId;
65 jfieldID mChangingConfigurations;
66 jfieldID mDensity;
67} gTypedValueOffsets;
68
69static struct assetfiledescriptor_offsets_t
70{
71 jfieldID mFd;
72 jfieldID mStartOffset;
73 jfieldID mLength;
74} gAssetFileDescriptorOffsets;
75
76static struct assetmanager_offsets_t
77{
78 jfieldID mObject;
79} gAssetManagerOffsets;
80
Adam Lesinskide898ff2014-01-29 18:20:45 -080081static struct sparsearray_offsets_t
82{
83 jclass classObject;
84 jmethodID constructor;
85 jmethodID put;
86} gSparseArrayOffsets;
87
Filip Gruszczynski23493322015-07-29 17:02:59 -070088static struct configuration_offsets_t
89{
90 jclass classObject;
91 jmethodID constructor;
92 jfieldID mSmallestScreenWidthDpOffset;
93 jfieldID mScreenWidthDpOffset;
94 jfieldID mScreenHeightDpOffset;
95} gConfigurationOffsets;
96
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097jclass g_stringClass = NULL;
98
99// ----------------------------------------------------------------------------
100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700102 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 STYLE_TYPE = 0,
104 STYLE_DATA = 1,
105 STYLE_ASSET_COOKIE = 2,
106 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700107 STYLE_CHANGING_CONFIGURATIONS = 4,
108 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109};
110
111static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
112 const Res_value& value, uint32_t ref, ssize_t block,
113 uint32_t typeSpecFlags, ResTable_config* config = NULL);
114
115jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
116 const Res_value& value, uint32_t ref, ssize_t block,
117 uint32_t typeSpecFlags, ResTable_config* config)
118{
119 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
120 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000121 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
123 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
124 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
125 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
126 typeSpecFlags);
127 if (config != NULL) {
128 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
129 }
130 return block;
131}
132
Mårten Kongstad48d22322014-01-31 14:43:27 +0100133// This is called by zygote (running as user root) as part of preloadResources.
134static void verifySystemIdmaps()
135{
136 pid_t pid;
137 char system_id[10];
138
139 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
140
141 switch (pid = fork()) {
142 case -1:
143 ALOGE("failed to fork for idmap: %s", strerror(errno));
144 break;
145 case 0: // child
146 {
147 struct __user_cap_header_struct capheader;
148 struct __user_cap_data_struct capdata;
149
150 memset(&capheader, 0, sizeof(capheader));
151 memset(&capdata, 0, sizeof(capdata));
152
153 capheader.version = _LINUX_CAPABILITY_VERSION;
154 capheader.pid = 0;
155
156 if (capget(&capheader, &capdata) != 0) {
157 ALOGE("capget: %s\n", strerror(errno));
158 exit(1);
159 }
160
161 capdata.effective = capdata.permitted;
162 if (capset(&capheader, &capdata) != 0) {
163 ALOGE("capset: %s\n", strerror(errno));
164 exit(1);
165 }
166
167 if (setgid(AID_SYSTEM) != 0) {
168 ALOGE("setgid: %s\n", strerror(errno));
169 exit(1);
170 }
171
172 if (setuid(AID_SYSTEM) != 0) {
173 ALOGE("setuid: %s\n", strerror(errno));
174 exit(1);
175 }
176
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100177 // Generic idmap parameters
178 const char* argv[7];
179 int argc = 0;
180 struct stat st;
181
182 memset(argv, NULL, sizeof(argv));
183 argv[argc++] = AssetManager::IDMAP_BIN;
184 argv[argc++] = "--scan";
185 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
186 argv[argc++] = AssetManager::TARGET_APK_PATH;
187 argv[argc++] = AssetManager::IDMAP_DIR;
188
Jakub Adamekc03d9482016-09-30 09:19:09 +0100189 // Directories to scan for overlays: if OVERLAY_SKU_DIR_PROPERTY is defined,
190 // use OVERLAY_DIR/<value of OVERLAY_SKU_DIR_PROPERTY> if exists, otherwise
Jakub Adamek1c15c632016-09-23 09:07:11 +0100191 // use OVERLAY_DIR if exists.
192 char subdir[PROP_VALUE_MAX];
Jakub Adamekc03d9482016-09-30 09:19:09 +0100193 int len = __system_property_get(AssetManager::OVERLAY_SKU_DIR_PROPERTY, subdir);
194 String8 overlayPath;
Jakub Adamek1c15c632016-09-23 09:07:11 +0100195 if (len > 0) {
Jakub Adamekc03d9482016-09-30 09:19:09 +0100196 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
197 } else {
198 overlayPath = String8(AssetManager::OVERLAY_DIR);
199 }
200 if (stat(overlayPath.string(), &st) == 0) {
201 argv[argc++] = overlayPath.string();
Jakub Adamek1c15c632016-09-23 09:07:11 +0100202 }
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100203
204 // Finally, invoke idmap (if any overlay directory exists)
205 if (argc > 5) {
206 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
207 ALOGE("failed to execl for idmap: %s", strerror(errno));
208 exit(1); // should never get here
209 } else {
210 exit(0);
211 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100212 }
213 break;
214 default: // parent
215 waitpid(pid, NULL, 0);
216 break;
217 }
218}
219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220// ----------------------------------------------------------------------------
221
222// this guy is exported to other jni routines
223AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
224{
Ashok Bhat896043d2014-01-17 16:02:38 +0000225 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
226 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 if (am != NULL) {
228 return am;
229 }
230 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
231 return NULL;
232}
233
Ashok Bhat896043d2014-01-17 16:02:38 +0000234static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 jstring fileName, jint mode)
236{
237 AssetManager* am = assetManagerForJavaObject(env, clazz);
238 if (am == NULL) {
239 return 0;
240 }
241
Steve Block71f2cf12011-10-20 11:56:00 +0100242 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
Elliott Hughes69a017b2011-04-08 14:10:28 -0700244 ScopedUtfChars fileName8(env, fileName);
245 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000246 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 return -1;
248 }
249
250 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
251 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700252 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 return -1;
254 }
255
Elliott Hughes69a017b2011-04-08 14:10:28 -0700256 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257
258 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700259 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 return -1;
261 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262
263 //printf("Created Asset Stream: %p\n", a);
264
Ashok Bhat896043d2014-01-17 16:02:38 +0000265 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266}
267
268static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
269{
Kenny Rootddb76c42010-11-24 12:56:06 -0800270 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 int fd = a->openFileDescriptor(&startOffset, &length);
272 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700275 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 "This file can not be opened as a file descriptor; it is probably compressed");
277 return NULL;
278 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
281 if (offsets == 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 offsets[0] = startOffset;
287 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700290
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700291 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 if (fileDesc == NULL) {
293 close(fd);
294 return NULL;
295 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 return newParcelFileDescriptor(env, fileDesc);
298}
299
300static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
301 jstring fileName, jlongArray outOffsets)
302{
303 AssetManager* am = assetManagerForJavaObject(env, clazz);
304 if (am == NULL) {
305 return NULL;
306 }
307
Steve Block71f2cf12011-10-20 11:56:00 +0100308 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309
Elliott Hughes69a017b2011-04-08 14:10:28 -0700310 ScopedUtfChars fileName8(env, fileName);
311 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 return NULL;
313 }
314
Elliott Hughes69a017b2011-04-08 14:10:28 -0700315 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700318 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 return NULL;
320 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
322 //printf("Created Asset Stream: %p\n", a);
323
324 return returnParcelFileDescriptor(env, a, outOffsets);
325}
326
Ashok Bhat896043d2014-01-17 16:02:38 +0000327static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 jint cookie,
329 jstring fileName,
330 jint mode)
331{
332 AssetManager* am = assetManagerForJavaObject(env, clazz);
333 if (am == NULL) {
334 return 0;
335 }
336
Steve Block71f2cf12011-10-20 11:56:00 +0100337 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338
Elliott Hughes69a017b2011-04-08 14:10:28 -0700339 ScopedUtfChars fileName8(env, fileName);
340 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 return -1;
342 }
343
344 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
345 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700346 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 return -1;
348 }
349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000351 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
352 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700353 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
355 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700356 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 return -1;
358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
360 //printf("Created Asset Stream: %p\n", a);
361
Ashok Bhat896043d2014-01-17 16:02:38 +0000362 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363}
364
365static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
366 jint cookie,
367 jstring fileName,
368 jlongArray outOffsets)
369{
370 AssetManager* am = assetManagerForJavaObject(env, clazz);
371 if (am == NULL) {
372 return NULL;
373 }
374
Steve Block71f2cf12011-10-20 11:56:00 +0100375 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376
Elliott Hughes69a017b2011-04-08 14:10:28 -0700377 ScopedUtfChars fileName8(env, fileName);
378 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 return NULL;
380 }
381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000383 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700384 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385
386 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700387 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 return NULL;
389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390
391 //printf("Created Asset Stream: %p\n", a);
392
393 return returnParcelFileDescriptor(env, a, outOffsets);
394}
395
396static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
397 jstring fileName)
398{
399 AssetManager* am = assetManagerForJavaObject(env, clazz);
400 if (am == NULL) {
401 return NULL;
402 }
403
Elliott Hughes69a017b2011-04-08 14:10:28 -0700404 ScopedUtfChars fileName8(env, fileName);
405 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 return NULL;
407 }
408
Elliott Hughes69a017b2011-04-08 14:10:28 -0700409 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410
411 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700412 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 return NULL;
414 }
415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 size_t N = dir->getFileCount();
417
418 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100419 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 delete dir;
422 return NULL;
423 }
424
425 for (size_t i=0; i<N; i++) {
426 const String8& name = dir->getFileName(i);
427 jstring str = env->NewStringUTF(name.string());
428 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 delete dir;
430 return NULL;
431 }
432 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700433 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 }
435
436 delete dir;
437
438 return array;
439}
440
441static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000442 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443{
Ashok Bhat896043d2014-01-17 16:02:38 +0000444 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445
446 //printf("Destroying Asset Stream: %p\n", a);
447
448 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700449 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 return;
451 }
452
453 delete a;
454}
455
456static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000457 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458{
Ashok Bhat896043d2014-01-17 16:02:38 +0000459 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460
461 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700462 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 return -1;
464 }
465
466 uint8_t b;
467 ssize_t res = a->read(&b, 1);
468 return res == 1 ? b : -1;
469}
470
471static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000472 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 jint off, jint len)
474{
Ashok Bhat896043d2014-01-17 16:02:38 +0000475 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476
477 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700478 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 return -1;
480 }
481
482 if (len == 0) {
483 return 0;
484 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 jsize bLen = env->GetArrayLength(bArray);
487 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700488 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 return -1;
490 }
491
492 jbyte* b = env->GetByteArrayElements(bArray, NULL);
493 ssize_t res = a->read(b+off, len);
494 env->ReleaseByteArrayElements(bArray, b, 0);
495
Ashok Bhat896043d2014-01-17 16:02:38 +0000496 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497
498 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700499 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 }
501 return -1;
502}
503
504static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000505 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 jlong offset, jint whence)
507{
Ashok Bhat896043d2014-01-17 16:02:38 +0000508 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509
510 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700511 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 return -1;
513 }
514
515 return a->seek(
516 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
517}
518
519static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000520 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521{
Ashok Bhat896043d2014-01-17 16:02:38 +0000522 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523
524 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700525 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 return -1;
527 }
528
529 return a->getLength();
530}
531
532static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000533 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534{
Ashok Bhat896043d2014-01-17 16:02:38 +0000535 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536
537 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700538 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 return -1;
540 }
541
542 return a->getRemainingLength();
543}
544
545static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
Tao Baia6d7e3f2015-09-01 18:49:54 -0700546 jstring path, jboolean appAsLib)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800547{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700548 ScopedUtfChars path8(env, path);
549 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800550 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 }
552
553 AssetManager* am = assetManagerForJavaObject(env, clazz);
554 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800555 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 }
557
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000558 int32_t cookie;
Tao Baia6d7e3f2015-09-01 18:49:54 -0700559 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000561 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562}
563
Mårten Kongstad48d22322014-01-31 14:43:27 +0100564static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
565 jstring idmapPath)
566{
567 ScopedUtfChars idmapPath8(env, idmapPath);
568 if (idmapPath8.c_str() == NULL) {
569 return 0;
570 }
571
572 AssetManager* am = assetManagerForJavaObject(env, clazz);
573 if (am == NULL) {
574 return 0;
575 }
576
577 int32_t cookie;
578 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
579
580 return (res) ? (jint)cookie : 0;
581}
582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800583static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
584{
585 AssetManager* am = assetManagerForJavaObject(env, clazz);
586 if (am == NULL) {
587 return JNI_TRUE;
588 }
589 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
590}
591
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800592static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593{
594 Vector<String8> locales;
595
596 AssetManager* am = assetManagerForJavaObject(env, clazz);
597 if (am == NULL) {
598 return NULL;
599 }
600
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800601 am->getLocales(&locales, includeSystemLocales);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602
603 const int N = locales.size();
604
605 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
606 if (result == NULL) {
607 return NULL;
608 }
609
610 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700611 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700612 if (str == NULL) {
613 return NULL;
614 }
615 env->SetObjectArrayElement(result, i, str);
616 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 }
618
619 return result;
620}
621
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800622static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
623{
624 return getLocales(env, clazz, true /* include system locales */);
625}
626
627static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
628{
629 return getLocales(env, clazz, false /* don't include system locales */);
630}
631
Filip Gruszczynski23493322015-07-29 17:02:59 -0700632static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
633 jobject result = env->NewObject(gConfigurationOffsets.classObject,
634 gConfigurationOffsets.constructor);
635 if (result == NULL) {
636 return NULL;
637 }
638
639 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
640 config.smallestScreenWidthDp);
641 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
642 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
643
644 return result;
645}
646
647static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
648 const Vector<ResTable_config>& configs) {
649 const int N = configs.size();
650 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
651 if (result == NULL) {
652 return NULL;
653 }
654
655 for (int i=0; i<N; i++) {
656 jobject config = constructConfigurationObject(env, configs[i]);
657 if (config == NULL) {
658 env->DeleteLocalRef(result);
659 return NULL;
660 }
661
662 env->SetObjectArrayElement(result, i, config);
663 env->DeleteLocalRef(config);
664 }
665
666 return result;
667}
668
669static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
670 AssetManager* am = assetManagerForJavaObject(env, clazz);
671 if (am == NULL) {
672 return NULL;
673 }
674
675 const ResTable& res(am->getResources());
676 Vector<ResTable_config> configs;
677 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
678
679 return getSizeConfigurationsInternal(env, configs);
680}
681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
683 jint mcc, jint mnc,
684 jstring locale, jint orientation,
685 jint touchscreen, jint density,
686 jint keyboard, jint keyboardHidden,
687 jint navigation,
688 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700689 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700690 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100691 jint screenLayout, jint uiMode,
692 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693{
694 AssetManager* am = assetManagerForJavaObject(env, clazz);
695 if (am == NULL) {
696 return;
697 }
698
699 ResTable_config config;
700 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700703
Adam Lesinski2738c962015-05-14 14:25:36 -0700704 // Constants duplicated from Java class android.content.res.Configuration.
705 static const jint kScreenLayoutRoundMask = 0x300;
706 static const jint kScreenLayoutRoundShift = 8;
707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 config.mcc = (uint16_t)mcc;
709 config.mnc = (uint16_t)mnc;
710 config.orientation = (uint8_t)orientation;
711 config.touchscreen = (uint8_t)touchscreen;
712 config.density = (uint16_t)density;
713 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700714 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 config.navigation = (uint8_t)navigation;
716 config.screenWidth = (uint16_t)screenWidth;
717 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700718 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700719 config.screenWidthDp = (uint16_t)screenWidthDp;
720 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700721 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100722 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 config.sdkVersion = (uint16_t)sdkVersion;
724 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700725
726 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
727 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
728 // into screenLayout2.
729 config.screenLayout2 =
730 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
735}
736
737static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
738 jstring name,
739 jstring defType,
740 jstring defPackage)
741{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700742 ScopedStringChars name16(env, name);
743 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 return 0;
745 }
746
747 AssetManager* am = assetManagerForJavaObject(env, clazz);
748 if (am == NULL) {
749 return 0;
750 }
751
Dan Albert66987492014-11-20 11:41:21 -0800752 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
753 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
754 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 jsize defTypeLen = defType
756 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800757 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
758 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
759 NULL))
760 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 jsize defPackageLen = defPackage
762 ? env->GetStringLength(defPackage) : 0;
763
764 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800765 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
766 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767
768 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800769 env->ReleaseStringChars(defPackage,
770 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 }
772 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800773 env->ReleaseStringChars(defType,
774 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776
777 return ident;
778}
779
780static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
781 jint resid)
782{
783 AssetManager* am = assetManagerForJavaObject(env, clazz);
784 if (am == NULL) {
785 return NULL;
786 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700789 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 return NULL;
791 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 String16 str;
794 if (name.package != NULL) {
795 str.setTo(name.package, name.packageLen);
796 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700797 if (name.type8 != NULL || name.type != 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.type8 != NULL) {
803 str.append(String16(name.type8, name.typeLen));
804 } else {
805 str.append(name.type, name.typeLen);
806 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800807 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700808 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 if (str.size() > 0) {
810 char16_t div = '/';
811 str.append(&div, 1);
812 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700813 if (name.name8 != NULL) {
814 str.append(String16(name.name8, name.nameLen));
815 } else {
816 str.append(name.name, name.nameLen);
817 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 return env->NewString((const jchar*)str.string(), str.size());
821}
822
823static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
824 jint resid)
825{
826 AssetManager* am = assetManagerForJavaObject(env, clazz);
827 if (am == NULL) {
828 return NULL;
829 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700832 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 return NULL;
834 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836 if (name.package != NULL) {
837 return env->NewString((const jchar*)name.package, name.packageLen);
838 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 return NULL;
841}
842
843static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
844 jint resid)
845{
846 AssetManager* am = assetManagerForJavaObject(env, clazz);
847 if (am == NULL) {
848 return NULL;
849 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700852 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 return NULL;
854 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700855
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700856 if (name.type8 != NULL) {
857 return env->NewStringUTF(name.type8);
858 }
859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800860 if (name.type != NULL) {
861 return env->NewString((const jchar*)name.type, name.typeLen);
862 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 return NULL;
865}
866
867static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
868 jint resid)
869{
870 AssetManager* am = assetManagerForJavaObject(env, clazz);
871 if (am == NULL) {
872 return NULL;
873 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700876 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 return NULL;
878 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700879
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700880 if (name.name8 != NULL) {
881 return env->NewStringUTF(name.name8);
882 }
883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 if (name.name != NULL) {
885 return env->NewString((const jchar*)name.name, name.nameLen);
886 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800888 return NULL;
889}
890
891static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
892 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700893 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 jobject outValue,
895 jboolean resolve)
896{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800897 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800898 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700899 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800900 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 AssetManager* am = assetManagerForJavaObject(env, clazz);
902 if (am == NULL) {
903 return 0;
904 }
905 const ResTable& res(am->getResources());
906
907 Res_value value;
908 ResTable_config config;
909 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700910 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800911 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800912 if (block == BAD_INDEX) {
913 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
914 return 0;
915 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800916 }
917 uint32_t ref = ident;
918 if (resolve) {
919 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
920 if (kThrowOnBadId) {
921 if (block == BAD_INDEX) {
922 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
923 return 0;
924 }
925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000927 if (block >= 0) {
928 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
929 }
930
931 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932}
933
934static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
935 jint ident, jint bagEntryId,
936 jobject outValue, jboolean resolve)
937{
938 AssetManager* am = assetManagerForJavaObject(env, clazz);
939 if (am == NULL) {
940 return 0;
941 }
942 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 // Now lock down the resource object and start pulling stuff from it.
945 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 ssize_t block = -1;
948 Res_value value;
949
950 const ResTable::bag_entry* entry = NULL;
951 uint32_t typeSpecFlags;
952 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
953
954 for (ssize_t i=0; i<entryCount; i++) {
955 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
956 block = entry->stringBlock;
957 value = entry->map.value;
958 }
959 entry++;
960 }
961
962 res.unlock();
963
964 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000965 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 uint32_t ref = ident;
969 if (resolve) {
970 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800971 if (kThrowOnBadId) {
972 if (block == BAD_INDEX) {
973 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
974 return 0;
975 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800976 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000978 if (block >= 0) {
979 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
980 }
981
982 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983}
984
985static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
986{
987 AssetManager* am = assetManagerForJavaObject(env, clazz);
988 if (am == NULL) {
989 return 0;
990 }
991 return am->getResources().getTableCount();
992}
993
Ashok Bhat896043d2014-01-17 16:02:38 +0000994static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 jint block)
996{
997 AssetManager* am = assetManagerForJavaObject(env, clazz);
998 if (am == NULL) {
999 return 0;
1000 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001001 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002}
1003
1004static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
1005 jint cookie)
1006{
1007 AssetManager* am = assetManagerForJavaObject(env, clazz);
1008 if (am == NULL) {
1009 return NULL;
1010 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +00001011 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001012 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001013 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 return NULL;
1015 }
1016 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017 return str;
1018}
1019
Adam Lesinskide898ff2014-01-29 18:20:45 -08001020static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1021{
1022 AssetManager* am = assetManagerForJavaObject(env, clazz);
1023 if (am == NULL) {
1024 return 0;
1025 }
1026
1027 const ResTable& res = am->getResources();
1028
1029 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1030 gSparseArrayOffsets.constructor);
1031 const size_t N = res.getBasePackageCount();
1032 for (size_t i = 0; i < N; i++) {
1033 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -08001034 env->CallVoidMethod(
1035 sparseArray, gSparseArrayOffsets.put,
1036 static_cast<jint>(res.getBasePackageId(i)),
1037 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1038 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -08001039 }
1040 return sparseArray;
1041}
1042
Ashok Bhat896043d2014-01-17 16:02:38 +00001043static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044{
1045 AssetManager* am = assetManagerForJavaObject(env, clazz);
1046 if (am == NULL) {
1047 return 0;
1048 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001049 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050}
1051
1052static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001053 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054{
Ashok Bhat896043d2014-01-17 16:02:38 +00001055 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 delete theme;
1057}
1058
1059static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001060 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 jint styleRes,
1062 jboolean force)
1063{
Ashok Bhat896043d2014-01-17 16:02:38 +00001064 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 theme->applyStyle(styleRes, force ? true : false);
1066}
1067
1068static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001069 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070{
Ashok Bhat896043d2014-01-17 16:02:38 +00001071 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1072 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 dest->setTo(*src);
1074}
1075
Alan Viverettee54d2452015-05-06 10:41:43 -07001076static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1077{
1078 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1079 theme->clear();
1080}
1081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001083 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084{
Ashok Bhat896043d2014-01-17 16:02:38 +00001085 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 const ResTable& res(theme->getResTable());
1087
1088 Res_value value;
1089 // XXX value could be different in different configs!
1090 uint32_t typeSpecFlags = 0;
1091 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1092 uint32_t ref = 0;
1093 if (resolve) {
1094 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001095 if (kThrowOnBadId) {
1096 if (block == BAD_INDEX) {
1097 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1098 return 0;
1099 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 }
1102 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1103}
1104
Alan Viverettec1d52792015-05-05 09:49:03 -07001105static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1106 jlong themeHandle)
1107{
1108 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1109 return theme->getChangingConfigurations();
1110}
1111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001113 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001114 jstring tag, jstring prefix)
1115{
Ashok Bhat896043d2014-01-17 16:02:38 +00001116 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001118 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 // XXX Need to use params.
1121 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122}
1123
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001124class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1125public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -07001126 explicit XmlAttributeFinder(const ResXMLParser* parser)
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001127 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1128 , mParser(parser) {}
1129
1130 inline uint32_t getAttribute(jsize index) const {
1131 return mParser->getAttributeNameResID(index);
1132 }
1133
1134private:
1135 const ResXMLParser* mParser;
1136};
1137
1138class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1139public:
1140 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1141 : BackTrackingAttributeFinder(start, end) {}
1142
1143 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1144 return entry->map.name.ident;
1145 }
1146};
1147
Alan Viverette52b999f2014-03-24 18:00:26 -07001148static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1149 jlong themeToken,
1150 jint defStyleAttr,
1151 jint defStyleRes,
1152 jintArray inValues,
1153 jintArray attrs,
1154 jintArray outValues,
1155 jintArray outIndices)
1156{
1157 if (themeToken == 0) {
1158 jniThrowNullPointerException(env, "theme token");
1159 return JNI_FALSE;
1160 }
1161 if (attrs == NULL) {
1162 jniThrowNullPointerException(env, "attrs");
1163 return JNI_FALSE;
1164 }
1165 if (outValues == NULL) {
1166 jniThrowNullPointerException(env, "out values");
1167 return JNI_FALSE;
1168 }
1169
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001170 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001171 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1172 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001173 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001174
1175 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1176 const ResTable& res = theme->getResTable();
1177 ResTable_config config;
1178 Res_value value;
1179
1180 const jsize NI = env->GetArrayLength(attrs);
1181 const jsize NV = env->GetArrayLength(outValues);
1182 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1183 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1184 return JNI_FALSE;
1185 }
1186
1187 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1188 if (src == NULL) {
1189 return JNI_FALSE;
1190 }
1191
1192 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1193 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1194
1195 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1196 jint* dest = baseDest;
1197 if (dest == NULL) {
1198 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1199 return JNI_FALSE;
1200 }
1201
1202 jint* indices = NULL;
1203 int indicesIdx = 0;
1204 if (outIndices != NULL) {
1205 if (env->GetArrayLength(outIndices) > NI) {
1206 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1207 }
1208 }
1209
1210 // Load default style from attribute, if specified...
1211 uint32_t defStyleBagTypeSetFlags = 0;
1212 if (defStyleAttr != 0) {
1213 Res_value value;
1214 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1215 if (value.dataType == Res_value::TYPE_REFERENCE) {
1216 defStyleRes = value.data;
1217 }
1218 }
1219 }
1220
1221 // Now lock down the resource object and start pulling stuff from it.
1222 res.lock();
1223
1224 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001225 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001226 uint32_t defStyleTypeSetFlags = 0;
1227 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001228 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001229 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001230 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1231 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001232
1233 // Now iterate through all of the attributes that the client has requested,
1234 // filling in each with whatever data we can find.
1235 ssize_t block = 0;
1236 uint32_t typeSetFlags;
1237 for (jsize ii=0; ii<NI; ii++) {
1238 const uint32_t curIdent = (uint32_t)src[ii];
1239
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001240 if (kDebugStyles) {
1241 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1242 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001243
1244 // Try to find a value for this attribute... we prioritize values
1245 // coming from, first XML attributes, then XML style, then default
1246 // style, and finally the theme.
1247 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001248 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001249 typeSetFlags = 0;
1250 config.density = 0;
1251
1252 // Retrieve the current input value if available.
1253 if (NSV > 0 && srcValues[ii] != 0) {
1254 block = -1;
1255 value.dataType = Res_value::TYPE_ATTRIBUTE;
1256 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001257 if (kDebugStyles) {
1258 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1259 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001260 }
1261
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001262 if (value.dataType == Res_value::TYPE_NULL) {
1263 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1264 if (defStyleEntry != defStyleEnd) {
1265 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001266 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001267 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001268 if (kDebugStyles) {
1269 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1270 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001271 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001272 }
1273
1274 uint32_t resid = 0;
1275 if (value.dataType != Res_value::TYPE_NULL) {
1276 // Take care of resolving the found resource to its final value.
1277 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1278 &resid, &typeSetFlags, &config);
1279 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001280 if (kDebugStyles) {
1281 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1282 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001283 } else {
1284 // If we still don't have a value for this attribute, try to find
1285 // it in the theme!
1286 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1287 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001288 if (kDebugStyles) {
1289 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1290 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001291 newBlock = res.resolveReference(&value, block, &resid,
1292 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001293 if (kThrowOnBadId) {
1294 if (newBlock == BAD_INDEX) {
1295 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1296 return JNI_FALSE;
1297 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001298 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001299 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001300 if (kDebugStyles) {
1301 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1302 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001303 }
1304 }
1305
1306 // Deal with the special @null value -- it turns back to TYPE_NULL.
1307 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001308 if (kDebugStyles) {
1309 ALOGI("-> Setting to @null!");
1310 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001311 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001312 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001313 block = -1;
1314 }
1315
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001316 if (kDebugStyles) {
1317 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1318 value.data);
1319 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001320
1321 // Write the final value back to Java.
1322 dest[STYLE_TYPE] = value.dataType;
1323 dest[STYLE_DATA] = value.data;
1324 dest[STYLE_ASSET_COOKIE] =
1325 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1326 dest[STYLE_RESOURCE_ID] = resid;
1327 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1328 dest[STYLE_DENSITY] = config.density;
1329
1330 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1331 indicesIdx++;
1332 indices[indicesIdx] = ii;
1333 }
1334
1335 dest += STYLE_NUM_ENTRIES;
1336 }
1337
1338 res.unlock();
1339
1340 if (indices != NULL) {
1341 indices[0] = indicesIdx;
1342 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1343 }
1344 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1345 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1346 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1347
1348 return JNI_TRUE;
1349}
1350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001352 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 jint defStyleAttr,
1354 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001355 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 jintArray attrs,
1357 jintArray outValues,
1358 jintArray outIndices)
1359{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001360 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001361 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001362 return JNI_FALSE;
1363 }
1364 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001365 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001366 return JNI_FALSE;
1367 }
1368 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001369 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 return JNI_FALSE;
1371 }
1372
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001373 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001374 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1375 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1376 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001377 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001378
Ashok Bhat896043d2014-01-17 16:02:38 +00001379 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001381 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001382 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 Res_value value;
1384
1385 const jsize NI = env->GetArrayLength(attrs);
1386 const jsize NV = env->GetArrayLength(outValues);
1387 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001388 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 return JNI_FALSE;
1390 }
1391
1392 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1393 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 return JNI_FALSE;
1395 }
1396
1397 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1398 jint* dest = baseDest;
1399 if (dest == NULL) {
1400 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 return JNI_FALSE;
1402 }
1403
1404 jint* indices = NULL;
1405 int indicesIdx = 0;
1406 if (outIndices != NULL) {
1407 if (env->GetArrayLength(outIndices) > NI) {
1408 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1409 }
1410 }
1411
1412 // Load default style from attribute, if specified...
1413 uint32_t defStyleBagTypeSetFlags = 0;
1414 if (defStyleAttr != 0) {
1415 Res_value value;
1416 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1417 if (value.dataType == Res_value::TYPE_REFERENCE) {
1418 defStyleRes = value.data;
1419 }
1420 }
1421 }
1422
1423 // Retrieve the style class associated with the current XML tag.
1424 int style = 0;
1425 uint32_t styleBagTypeSetFlags = 0;
1426 if (xmlParser != NULL) {
1427 ssize_t idx = xmlParser->indexOfStyle();
1428 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1429 if (value.dataType == value.TYPE_ATTRIBUTE) {
1430 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1431 value.dataType = Res_value::TYPE_NULL;
1432 }
1433 }
1434 if (value.dataType == value.TYPE_REFERENCE) {
1435 style = value.data;
1436 }
1437 }
1438 }
1439
1440 // Now lock down the resource object and start pulling stuff from it.
1441 res.lock();
1442
1443 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001444 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 uint32_t defStyleTypeSetFlags = 0;
1446 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001447 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001449 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1450 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451
1452 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001453 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001455 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001457 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1458 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459
1460 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001462 XmlAttributeFinder xmlAttrFinder(xmlParser);
1463 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464
1465 // Now iterate through all of the attributes that the client has requested,
1466 // filling in each with whatever data we can find.
1467 ssize_t block = 0;
1468 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001469 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 const uint32_t curIdent = (uint32_t)src[ii];
1471
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001472 if (kDebugStyles) {
1473 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1474 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 // Try to find a value for this attribute... we prioritize values
1477 // coming from, first XML attributes, then XML style, then default
1478 // style, and finally the theme.
1479 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001480 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001482 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001484 // Walk through the xml attributes looking for the requested attribute.
1485 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1486 if (xmlAttrIdx != xmlAttrEnd) {
1487 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001489 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001490 if (kDebugStyles) {
1491 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001493 }
1494
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001495 if (value.dataType == Res_value::TYPE_NULL) {
1496 // Walk through the style class values looking for the requested attribute.
1497 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1498 if (styleAttrEntry != styleAttrEnd) {
1499 // We found the attribute we were looking for.
1500 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001502 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001503 if (kDebugStyles) {
1504 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 }
1508
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001509 if (value.dataType == Res_value::TYPE_NULL) {
1510 // Walk through the default style values looking for the requested attribute.
1511 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1512 if (defStyleAttrEntry != defStyleAttrEnd) {
1513 // We found the attribute we were looking for.
1514 block = defStyleAttrEntry->stringBlock;
1515 typeSetFlags = styleTypeSetFlags;
1516 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001517 if (kDebugStyles) {
1518 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 }
1522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 uint32_t resid = 0;
1524 if (value.dataType != Res_value::TYPE_NULL) {
1525 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001526 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1527 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001528 if (newBlock >= 0) {
1529 block = newBlock;
1530 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001531
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001532 if (kDebugStyles) {
1533 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1534 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 } else {
1536 // If we still don't have a value for this attribute, try to find
1537 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1539 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001540 if (kDebugStyles) {
1541 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1542 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001543 newBlock = res.resolveReference(&value, block, &resid,
1544 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001545 if (kThrowOnBadId) {
1546 if (newBlock == BAD_INDEX) {
1547 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1548 return JNI_FALSE;
1549 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001550 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001551
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001552 if (newBlock >= 0) {
1553 block = newBlock;
1554 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001555
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001556 if (kDebugStyles) {
1557 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 }
1561
1562 // Deal with the special @null value -- it turns back to TYPE_NULL.
1563 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001564 if (kDebugStyles) {
1565 ALOGI("-> Setting to @null!");
1566 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001568 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001569 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 }
1571
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001572 if (kDebugStyles) {
1573 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1574 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575
1576 // Write the final value back to Java.
1577 dest[STYLE_TYPE] = value.dataType;
1578 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001579 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1580 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 dest[STYLE_RESOURCE_ID] = resid;
1582 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001583 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1586 indicesIdx++;
1587 indices[indicesIdx] = ii;
1588 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 dest += STYLE_NUM_ENTRIES;
1591 }
1592
1593 res.unlock();
1594
1595 if (indices != NULL) {
1596 indices[0] = indicesIdx;
1597 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1598 }
1599 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1600 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1601
1602 return JNI_TRUE;
1603}
1604
1605static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001606 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 jintArray attrs,
1608 jintArray outValues,
1609 jintArray outIndices)
1610{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001611 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001613 return JNI_FALSE;
1614 }
1615 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001616 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001617 return JNI_FALSE;
1618 }
1619 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001620 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 return JNI_FALSE;
1622 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 AssetManager* am = assetManagerForJavaObject(env, clazz);
1625 if (am == NULL) {
1626 return JNI_FALSE;
1627 }
1628 const ResTable& res(am->getResources());
1629 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001630 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 const jsize NI = env->GetArrayLength(attrs);
1634 const jsize NV = env->GetArrayLength(outValues);
1635 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001636 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return JNI_FALSE;
1638 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1641 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 return JNI_FALSE;
1643 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001644
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1646 jint* dest = baseDest;
1647 if (dest == NULL) {
1648 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 return JNI_FALSE;
1650 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 jint* indices = NULL;
1653 int indicesIdx = 0;
1654 if (outIndices != NULL) {
1655 if (env->GetArrayLength(outIndices) > NI) {
1656 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1657 }
1658 }
1659
1660 // Now lock down the resource object and start pulling stuff from it.
1661 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 // Retrieve the XML attributes, if requested.
1664 const jsize NX = xmlParser->getAttributeCount();
1665 jsize ix=0;
1666 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 // Now iterate through all of the attributes that the client has requested,
1671 // filling in each with whatever data we can find.
1672 ssize_t block = 0;
1673 uint32_t typeSetFlags;
1674 for (jsize ii=0; ii<NI; ii++) {
1675 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 // Try to find a value for this attribute...
1678 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001679 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001681 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001683 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001684 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 ix++;
1686 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1687 }
1688 // Retrieve the current XML attribute if it matches, and step to next.
1689 if (ix < NX && curIdent == curXmlAttr) {
1690 block = kXmlBlock;
1691 xmlParser->getAttributeValue(ix, &value);
1692 ix++;
1693 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1694 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001696 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1697 uint32_t resid = 0;
1698 if (value.dataType != Res_value::TYPE_NULL) {
1699 // Take care of resolving the found resource to its final value.
1700 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001701 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1702 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001703 if (kThrowOnBadId) {
1704 if (newBlock == BAD_INDEX) {
1705 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1706 return JNI_FALSE;
1707 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001708 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 if (newBlock >= 0) block = newBlock;
1710 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 // Deal with the special @null value -- it turns back to TYPE_NULL.
1713 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1714 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001715 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 // Write the final value back to Java.
1721 dest[STYLE_TYPE] = value.dataType;
1722 dest[STYLE_DATA] = value.data;
1723 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001724 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 dest[STYLE_RESOURCE_ID] = resid;
1726 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001727 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1730 indicesIdx++;
1731 indices[indicesIdx] = ii;
1732 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 dest += STYLE_NUM_ENTRIES;
1735 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001737 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 if (indices != NULL) {
1740 indices[0] = indicesIdx;
1741 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1742 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1745 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 return JNI_TRUE;
1748}
1749
1750static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1751 jint id)
1752{
1753 AssetManager* am = assetManagerForJavaObject(env, clazz);
1754 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001755 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756 }
1757 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 res.lock();
1760 const ResTable::bag_entry* defStyleEnt = NULL;
1761 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1762 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001763
Ashok Bhat896043d2014-01-17 16:02:38 +00001764 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765}
1766
1767static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1768 jint id,
1769 jintArray outValues)
1770{
1771 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001772 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 return JNI_FALSE;
1774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 AssetManager* am = assetManagerForJavaObject(env, clazz);
1777 if (am == NULL) {
1778 return JNI_FALSE;
1779 }
1780 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001781 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 Res_value value;
1783 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1788 jint* dest = baseDest;
1789 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001790 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 return JNI_FALSE;
1792 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 // Now lock down the resource object and start pulling stuff from it.
1795 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 const ResTable::bag_entry* arrayEnt = NULL;
1798 uint32_t arrayTypeSetFlags = 0;
1799 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1800 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1801 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 int i = 0;
1804 uint32_t typeSetFlags;
1805 while (i < NV && arrayEnt < endArrayEnt) {
1806 block = arrayEnt->stringBlock;
1807 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001808 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001811 uint32_t resid = 0;
1812 if (value.dataType != Res_value::TYPE_NULL) {
1813 // Take care of resolving the found resource to its final value.
1814 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001815 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1816 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001817 if (kThrowOnBadId) {
1818 if (newBlock == BAD_INDEX) {
1819 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1820 return JNI_FALSE;
1821 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001823 if (newBlock >= 0) block = newBlock;
1824 }
1825
1826 // Deal with the special @null value -- it turns back to TYPE_NULL.
1827 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1828 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001829 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 }
1831
1832 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1833
1834 // Write the final value back to Java.
1835 dest[STYLE_TYPE] = value.dataType;
1836 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001837 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001838 dest[STYLE_RESOURCE_ID] = resid;
1839 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001840 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 dest += STYLE_NUM_ENTRIES;
1842 i+= STYLE_NUM_ENTRIES;
1843 arrayEnt++;
1844 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001850 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 return i;
1853}
1854
Ashok Bhat896043d2014-01-17 16:02:38 +00001855static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 jint cookie,
1857 jstring fileName)
1858{
1859 AssetManager* am = assetManagerForJavaObject(env, clazz);
1860 if (am == NULL) {
1861 return 0;
1862 }
1863
Steve Block71f2cf12011-10-20 11:56:00 +01001864 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001865
Elliott Hughes69a017b2011-04-08 14:10:28 -07001866 ScopedUtfChars fileName8(env, fileName);
1867 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 return 0;
1869 }
1870
Adam Lesinskide898ff2014-01-29 18:20:45 -08001871 int32_t assetCookie = static_cast<int32_t>(cookie);
1872 Asset* a = assetCookie
1873 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1874 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875
1876 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001877 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 return 0;
1879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880
Adam Lesinskide898ff2014-01-29 18:20:45 -08001881 const DynamicRefTable* dynamicRefTable =
1882 am->getResources().getDynamicRefTableForCookie(assetCookie);
1883 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1885 a->close();
1886 delete a;
1887
1888 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001889 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 return 0;
1891 }
1892
Ashok Bhat896043d2014-01-17 16:02:38 +00001893 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894}
1895
1896static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1897 jint arrayResId)
1898{
1899 AssetManager* am = assetManagerForJavaObject(env, clazz);
1900 if (am == NULL) {
1901 return NULL;
1902 }
1903 const ResTable& res(am->getResources());
1904
1905 const ResTable::bag_entry* startOfBag;
1906 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1907 if (N < 0) {
1908 return NULL;
1909 }
1910
1911 jintArray array = env->NewIntArray(N * 2);
1912 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 res.unlockBag(startOfBag);
1914 return NULL;
1915 }
1916
1917 Res_value value;
1918 const ResTable::bag_entry* bag = startOfBag;
1919 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1920 jint stringIndex = -1;
1921 jint stringBlock = 0;
1922 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 // Take care of resolving the found resource to its final value.
1925 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1926 if (value.dataType == Res_value::TYPE_STRING) {
1927 stringIndex = value.data;
1928 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001929
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001930 if (kThrowOnBadId) {
1931 if (stringBlock == BAD_INDEX) {
1932 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1933 return array;
1934 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001935 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 //todo: It might be faster to allocate a C array to contain
1938 // the blocknums and indices, put them in there and then
1939 // do just one SetIntArrayRegion()
1940 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1941 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1942 j = j + 2;
1943 }
1944 res.unlockBag(startOfBag);
1945 return array;
1946}
1947
1948static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1949 jint arrayResId)
1950{
1951 AssetManager* am = assetManagerForJavaObject(env, clazz);
1952 if (am == NULL) {
1953 return NULL;
1954 }
1955 const ResTable& res(am->getResources());
1956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 const ResTable::bag_entry* startOfBag;
1958 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1959 if (N < 0) {
1960 return NULL;
1961 }
1962
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001963 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001964 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 res.unlockBag(startOfBag);
1966 return NULL;
1967 }
1968
1969 Res_value value;
1970 const ResTable::bag_entry* bag = startOfBag;
1971 size_t strLen = 0;
1972 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1973 value = bag->map.value;
1974 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 // Take care of resolving the found resource to its final value.
1977 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001978 if (kThrowOnBadId) {
1979 if (block == BAD_INDEX) {
1980 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1981 return array;
1982 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001985 const ResStringPool* pool = res.getTableStringBlock(block);
1986 const char* str8 = pool->string8At(value.data, &strLen);
1987 if (str8 != NULL) {
1988 str = env->NewStringUTF(str8);
1989 } else {
1990 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001991 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1992 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001993 }
1994
1995 // If one of our NewString{UTF} calls failed due to memory, an
1996 // exception will be pending.
1997 if (env->ExceptionCheck()) {
1998 res.unlockBag(startOfBag);
1999 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 }
Kenny Root780d2a12010-02-22 22:36:26 -08002001
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002002 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07002003
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002004 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
2005 // If we have a large amount of strings in our array, we might
2006 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07002007 env->DeleteLocalRef(str);
2008 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 }
2010 res.unlockBag(startOfBag);
2011 return array;
2012}
2013
2014static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
2015 jint arrayResId)
2016{
2017 AssetManager* am = assetManagerForJavaObject(env, clazz);
2018 if (am == NULL) {
2019 return NULL;
2020 }
2021 const ResTable& res(am->getResources());
2022
2023 const ResTable::bag_entry* startOfBag;
2024 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
2025 if (N < 0) {
2026 return NULL;
2027 }
2028
2029 jintArray array = env->NewIntArray(N);
2030 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 res.unlockBag(startOfBag);
2032 return NULL;
2033 }
2034
2035 Res_value value;
2036 const ResTable::bag_entry* bag = startOfBag;
2037 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2038 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07002039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 // Take care of resolving the found resource to its final value.
2041 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08002042 if (kThrowOnBadId) {
2043 if (block == BAD_INDEX) {
2044 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
2045 return array;
2046 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 if (value.dataType >= Res_value::TYPE_FIRST_INT
2049 && value.dataType <= Res_value::TYPE_LAST_INT) {
2050 int intVal = value.data;
2051 env->SetIntArrayRegion(array, i, 1, &intVal);
2052 }
2053 }
2054 res.unlockBag(startOfBag);
2055 return array;
2056}
2057
Jon Miranda042ad632014-09-03 17:57:35 -07002058static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
2059 jint styleId)
2060{
2061 AssetManager* am = assetManagerForJavaObject(env, clazz);
2062 if (am == NULL) {
2063 return NULL;
2064 }
2065 const ResTable& res(am->getResources());
2066
2067 const ResTable::bag_entry* startOfBag;
2068 const ssize_t N = res.lockBag(styleId, &startOfBag);
2069 if (N < 0) {
2070 return NULL;
2071 }
2072
2073 jintArray array = env->NewIntArray(N);
2074 if (array == NULL) {
2075 res.unlockBag(startOfBag);
2076 return NULL;
2077 }
2078
Jon Miranda042ad632014-09-03 17:57:35 -07002079 const ResTable::bag_entry* bag = startOfBag;
2080 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2081 int resourceId = bag->map.name.ident;
2082 env->SetIntArrayRegion(array, i, 1, &resourceId);
2083 }
2084 res.unlockBag(startOfBag);
2085 return array;
2086}
2087
Mårten Kongstad48d22322014-01-31 14:43:27 +01002088static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002090 if (isSystem) {
2091 verifySystemIdmaps();
2092 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 AssetManager* am = new AssetManager();
2094 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002095 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002096 return;
2097 }
2098
2099 am->addDefaultAssets();
2100
Steve Block71f2cf12011-10-20 11:56:00 +01002101 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002102 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103}
2104
2105static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2106{
2107 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002108 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002109 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 if (am != NULL) {
2111 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002112 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 }
2114}
2115
2116static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2117{
2118 return Asset::getGlobalCount();
2119}
2120
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002121static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2122{
2123 String8 alloc = Asset::getAssetAllocations();
2124 if (alloc.length() <= 0) {
2125 return NULL;
2126 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002127
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002128 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002129 return str;
2130}
2131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2133{
2134 return AssetManager::getGlobalCount();
2135}
2136
2137// ----------------------------------------------------------------------------
2138
2139/*
2140 * JNI registration.
2141 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002142static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 /* name, signature, funcPtr */
2144
2145 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002146 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 (void*) android_content_AssetManager_openAsset },
2148 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2149 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002150 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 (void*) android_content_AssetManager_openNonAssetNative },
2152 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2153 (void*) android_content_AssetManager_openNonAssetFdNative },
2154 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2155 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002156 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002158 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002159 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002160 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002162 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 (void*) android_content_AssetManager_seekAsset },
John Reck32995222016-10-07 11:02:20 -07002164 // @FastNative
2165 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 (void*) android_content_AssetManager_getAssetLength },
John Reck32995222016-10-07 11:02:20 -07002167 // @FastNative
2168 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 (void*) android_content_AssetManager_getAssetRemainingLength },
Tao Baia6d7e3f2015-09-01 18:49:54 -07002170 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002172 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002173 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 { "isUpToDate", "()Z",
2175 (void*) android_content_AssetManager_isUpToDate },
2176
2177 // Resources.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 { "getLocales", "()[Ljava/lang/String;",
2179 (void*) android_content_AssetManager_getLocales },
Roozbeh Pournader1c686f22015-12-18 14:22:14 -08002180 { "getNonSystemLocales", "()[Ljava/lang/String;",
2181 (void*) android_content_AssetManager_getNonSystemLocales },
Filip Gruszczynski23493322015-07-29 17:02:59 -07002182 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
2183 (void*) android_content_AssetManager_getSizeConfigurations },
John Reck32995222016-10-07 11:02:20 -07002184 // @FastNative
2185 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 (void*) android_content_AssetManager_setConfiguration },
John Reck32995222016-10-07 11:02:20 -07002187 // @FastNative
2188 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002189 (void*) android_content_AssetManager_getResourceIdentifier },
John Reck32995222016-10-07 11:02:20 -07002190 // @FastNative
2191 { "getResourceName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 (void*) android_content_AssetManager_getResourceName },
John Reck32995222016-10-07 11:02:20 -07002193 // @FastNative
2194 { "getResourcePackageName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002195 (void*) android_content_AssetManager_getResourcePackageName },
John Reck32995222016-10-07 11:02:20 -07002196 // @FastNative
2197 { "getResourceTypeName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 (void*) android_content_AssetManager_getResourceTypeName },
John Reck32995222016-10-07 11:02:20 -07002199 // @FastNative
2200 { "getResourceEntryName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002201 (void*) android_content_AssetManager_getResourceEntryName },
John Reck32995222016-10-07 11:02:20 -07002202 // @FastNative
2203 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002204 (void*) android_content_AssetManager_loadResourceValue },
John Reck32995222016-10-07 11:02:20 -07002205 // @FastNative
2206 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002207 (void*) android_content_AssetManager_loadResourceBagValue },
John Reck32995222016-10-07 11:02:20 -07002208 // @FastNative
2209 { "getStringBlockCount","()I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 (void*) android_content_AssetManager_getStringBlockCount },
John Reck32995222016-10-07 11:02:20 -07002211 // @FastNative
2212 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 (void*) android_content_AssetManager_getNativeStringBlock },
2214 { "getCookieName","(I)Ljava/lang/String;",
2215 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002216 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2217 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218
2219 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002220 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002221 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002222 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002224 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002226 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002227 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002228 { "clearTheme", "(J)V",
2229 (void*) android_content_AssetManager_clearTheme },
John Reck32995222016-10-07 11:02:20 -07002230 // @FastNative
2231 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 (void*) android_content_AssetManager_loadThemeAttributeValue },
John Reck32995222016-10-07 11:02:20 -07002233 // @FastNative
2234 { "getThemeChangingConfigurations", "(J)I",
Alan Viverettec1d52792015-05-05 09:49:03 -07002235 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002236 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237 (void*) android_content_AssetManager_dumpTheme },
John Reck32995222016-10-07 11:02:20 -07002238 // @FastNative
2239 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 (void*) android_content_AssetManager_applyStyle },
John Reck32995222016-10-07 11:02:20 -07002241 // @FastNative
2242 { "resolveAttrs","(JII[I[I[I[I)Z",
Alan Viverette607bd842014-09-12 12:36:35 -07002243 (void*) android_content_AssetManager_resolveAttrs },
John Reck32995222016-10-07 11:02:20 -07002244 // @FastNative
2245 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002246 (void*) android_content_AssetManager_retrieveAttributes },
John Reck32995222016-10-07 11:02:20 -07002247 // @FastNative
2248 { "getArraySize","(I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 (void*) android_content_AssetManager_getArraySize },
John Reck32995222016-10-07 11:02:20 -07002250 // @FastNative
2251 { "retrieveArray","(I[I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252 (void*) android_content_AssetManager_retrieveArray },
2253
2254 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002255 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 (void*) android_content_AssetManager_openXmlAssetNative },
2257
2258 // Arrays.
2259 { "getArrayStringResource","(I)[Ljava/lang/String;",
2260 (void*) android_content_AssetManager_getArrayStringResource },
John Reck32995222016-10-07 11:02:20 -07002261 // @FastNative
2262 { "getArrayStringInfo","(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263 (void*) android_content_AssetManager_getArrayStringInfo },
John Reck32995222016-10-07 11:02:20 -07002264 // @FastNative
2265 { "getArrayIntResource","(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002266 (void*) android_content_AssetManager_getArrayIntResource },
John Reck32995222016-10-07 11:02:20 -07002267 // @FastNative
2268 { "getStyleAttributes","(I)[I",
Jon Miranda042ad632014-09-03 17:57:35 -07002269 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002270
2271 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002272 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 (void*) android_content_AssetManager_init },
2274 { "destroy", "()V",
2275 (void*) android_content_AssetManager_destroy },
2276 { "getGlobalAssetCount", "()I",
2277 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002278 { "getAssetAllocations", "()Ljava/lang/String;",
2279 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002280 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002281 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282};
2283
2284int register_android_content_AssetManager(JNIEnv* env)
2285{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002286 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2287 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2288 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2289 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2290 "Ljava/lang/CharSequence;");
2291 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2292 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2293 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2294 "changingConfigurations", "I");
2295 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296
Andreas Gampe987f79f2014-11-18 17:29:46 -08002297 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2298 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2299 "Landroid/os/ParcelFileDescriptor;");
2300 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2301 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002302
Andreas Gampe987f79f2014-11-18 17:29:46 -08002303 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2304 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002305
Andreas Gampe987f79f2014-11-18 17:29:46 -08002306 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2307 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308
Andreas Gampe987f79f2014-11-18 17:29:46 -08002309 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2310 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2311 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2312 "<init>", "()V");
2313 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2314 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002315
Filip Gruszczynski23493322015-07-29 17:02:59 -07002316 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
2317 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
2318 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
2319 "<init>", "()V");
2320 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2321 "smallestScreenWidthDp", "I");
2322 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2323 "screenWidthDp", "I");
2324 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
2325 "screenHeightDp", "I");
2326
Andreas Gampe987f79f2014-11-18 17:29:46 -08002327 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2328 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002329}
2330
2331}; // namespace android