blob: 15966adcd33ce8f44fa2c1100a38bb983d318599 [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"
Steven Moreland2279b252017-07-19 09:50:45 -070040#include <nativehelper/JNIHelp.h>
41#include <nativehelper/ScopedStringChars.h>
42#include <nativehelper/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
Jakub Adamek56b99872016-10-20 15:07:57 +0100178 const char* argv[8];
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100179 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 Adamek54dcaab2016-10-19 11:46:13 +0100189 // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
190 // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
Jakub Adamek1c15c632016-09-23 09:07:11 +0100191 char subdir[PROP_VALUE_MAX];
Jakub Adamek54dcaab2016-10-19 11:46:13 +0100192 int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
Jakub Adamek1c15c632016-09-23 09:07:11 +0100193 if (len > 0) {
Jakub Adamek1f36a212016-10-17 14:53:40 +0100194 String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
195 if (stat(overlayPath.string(), &st) == 0) {
196 argv[argc++] = overlayPath.string();
197 }
Jakub Adamekc03d9482016-09-30 09:19:09 +0100198 }
Jakub Adamek1f36a212016-10-17 14:53:40 +0100199 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
200 argv[argc++] = AssetManager::OVERLAY_DIR;
Jakub Adamek1c15c632016-09-23 09:07:11 +0100201 }
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100202
203 // Finally, invoke idmap (if any overlay directory exists)
204 if (argc > 5) {
205 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
Jakub Adamek56b99872016-10-20 15:07:57 +0100206 ALOGE("failed to execv for idmap: %s", strerror(errno));
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100207 exit(1); // should never get here
208 } else {
209 exit(0);
210 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100211 }
212 break;
213 default: // parent
214 waitpid(pid, NULL, 0);
215 break;
216 }
217}
218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219// ----------------------------------------------------------------------------
220
221// this guy is exported to other jni routines
222AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
223{
Ashok Bhat896043d2014-01-17 16:02:38 +0000224 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
225 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 if (am != NULL) {
227 return am;
228 }
229 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
230 return NULL;
231}
232
Ashok Bhat896043d2014-01-17 16:02:38 +0000233static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 jstring fileName, jint mode)
235{
236 AssetManager* am = assetManagerForJavaObject(env, clazz);
237 if (am == NULL) {
238 return 0;
239 }
240
Steve Block71f2cf12011-10-20 11:56:00 +0100241 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242
Elliott Hughes69a017b2011-04-08 14:10:28 -0700243 ScopedUtfChars fileName8(env, fileName);
244 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000245 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 return -1;
247 }
248
249 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
250 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700251 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 return -1;
253 }
254
Elliott Hughes69a017b2011-04-08 14:10:28 -0700255 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256
257 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700258 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 return -1;
260 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261
262 //printf("Created Asset Stream: %p\n", a);
263
Ashok Bhat896043d2014-01-17 16:02:38 +0000264 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265}
266
267static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
268{
Kenny Rootddb76c42010-11-24 12:56:06 -0800269 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 int fd = a->openFileDescriptor(&startOffset, &length);
271 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700274 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 "This file can not be opened as a file descriptor; it is probably compressed");
276 return NULL;
277 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
280 if (offsets == NULL) {
281 close(fd);
282 return NULL;
283 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 offsets[0] = startOffset;
286 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700289
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700290 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 if (fileDesc == NULL) {
292 close(fd);
293 return NULL;
294 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 return newParcelFileDescriptor(env, fileDesc);
297}
298
299static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
300 jstring fileName, jlongArray outOffsets)
301{
302 AssetManager* am = assetManagerForJavaObject(env, clazz);
303 if (am == NULL) {
304 return NULL;
305 }
306
Steve Block71f2cf12011-10-20 11:56:00 +0100307 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
Elliott Hughes69a017b2011-04-08 14:10:28 -0700309 ScopedUtfChars fileName8(env, fileName);
310 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 return NULL;
312 }
313
Elliott Hughes69a017b2011-04-08 14:10:28 -0700314 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700317 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 return NULL;
319 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320
321 //printf("Created Asset Stream: %p\n", a);
322
323 return returnParcelFileDescriptor(env, a, outOffsets);
324}
325
Ashok Bhat896043d2014-01-17 16:02:38 +0000326static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 jint cookie,
328 jstring fileName,
329 jint mode)
330{
331 AssetManager* am = assetManagerForJavaObject(env, clazz);
332 if (am == NULL) {
333 return 0;
334 }
335
Steve Block71f2cf12011-10-20 11:56:00 +0100336 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337
Elliott Hughes69a017b2011-04-08 14:10:28 -0700338 ScopedUtfChars fileName8(env, fileName);
339 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 return -1;
341 }
342
343 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
344 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700345 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return -1;
347 }
348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000350 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
351 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700352 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353
354 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700355 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 return -1;
357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358
359 //printf("Created Asset Stream: %p\n", a);
360
Ashok Bhat896043d2014-01-17 16:02:38 +0000361 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362}
363
364static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
365 jint cookie,
366 jstring fileName,
367 jlongArray outOffsets)
368{
369 AssetManager* am = assetManagerForJavaObject(env, clazz);
370 if (am == NULL) {
371 return NULL;
372 }
373
Steve Block71f2cf12011-10-20 11:56:00 +0100374 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375
Elliott Hughes69a017b2011-04-08 14:10:28 -0700376 ScopedUtfChars fileName8(env, fileName);
377 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 return NULL;
379 }
380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000382 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700383 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384
385 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700386 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 return NULL;
388 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389
390 //printf("Created Asset Stream: %p\n", a);
391
392 return returnParcelFileDescriptor(env, a, outOffsets);
393}
394
395static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
396 jstring fileName)
397{
398 AssetManager* am = assetManagerForJavaObject(env, clazz);
399 if (am == NULL) {
400 return NULL;
401 }
402
Elliott Hughes69a017b2011-04-08 14:10:28 -0700403 ScopedUtfChars fileName8(env, fileName);
404 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 return NULL;
406 }
407
Elliott Hughes69a017b2011-04-08 14:10:28 -0700408 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409
410 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700411 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 return NULL;
413 }
414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 size_t N = dir->getFileCount();
416
417 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100418 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 delete dir;
421 return NULL;
422 }
423
424 for (size_t i=0; i<N; i++) {
425 const String8& name = dir->getFileName(i);
426 jstring str = env->NewStringUTF(name.string());
427 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 delete dir;
429 return NULL;
430 }
431 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700432 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 }
434
435 delete dir;
436
437 return array;
438}
439
440static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000441 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442{
Ashok Bhat896043d2014-01-17 16:02:38 +0000443 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444
445 //printf("Destroying Asset Stream: %p\n", a);
446
447 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700448 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 return;
450 }
451
452 delete a;
453}
454
455static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000456 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457{
Ashok Bhat896043d2014-01-17 16:02:38 +0000458 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459
460 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700461 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 return -1;
463 }
464
465 uint8_t b;
466 ssize_t res = a->read(&b, 1);
467 return res == 1 ? b : -1;
468}
469
470static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000471 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 jint off, jint len)
473{
Ashok Bhat896043d2014-01-17 16:02:38 +0000474 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475
476 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700477 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 return -1;
479 }
480
481 if (len == 0) {
482 return 0;
483 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 jsize bLen = env->GetArrayLength(bArray);
486 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700487 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 return -1;
489 }
490
491 jbyte* b = env->GetByteArrayElements(bArray, NULL);
492 ssize_t res = a->read(b+off, len);
493 env->ReleaseByteArrayElements(bArray, b, 0);
494
Ashok Bhat896043d2014-01-17 16:02:38 +0000495 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496
497 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700498 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 }
500 return -1;
501}
502
503static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000504 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 jlong offset, jint whence)
506{
Ashok Bhat896043d2014-01-17 16:02:38 +0000507 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508
509 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700510 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 return -1;
512 }
513
514 return a->seek(
515 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
516}
517
518static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000519 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520{
Ashok Bhat896043d2014-01-17 16:02:38 +0000521 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522
523 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700524 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 return -1;
526 }
527
528 return a->getLength();
529}
530
531static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000532 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533{
Ashok Bhat896043d2014-01-17 16:02:38 +0000534 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535
536 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700537 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 return -1;
539 }
540
541 return a->getRemainingLength();
542}
543
544static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
Tao Baia6d7e3f2015-09-01 18:49:54 -0700545 jstring path, jboolean appAsLib)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700547 ScopedUtfChars path8(env, path);
548 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800549 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 }
551
552 AssetManager* am = assetManagerForJavaObject(env, clazz);
553 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800554 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 }
556
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000557 int32_t cookie;
Tao Baia6d7e3f2015-09-01 18:49:54 -0700558 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000560 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561}
562
Mårten Kongstad48d22322014-01-31 14:43:27 +0100563static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
564 jstring idmapPath)
565{
566 ScopedUtfChars idmapPath8(env, idmapPath);
567 if (idmapPath8.c_str() == NULL) {
568 return 0;
569 }
570
571 AssetManager* am = assetManagerForJavaObject(env, clazz);
572 if (am == NULL) {
573 return 0;
574 }
575
576 int32_t cookie;
577 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
578
579 return (res) ? (jint)cookie : 0;
580}
581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
583{
584 AssetManager* am = assetManagerForJavaObject(env, clazz);
585 if (am == NULL) {
586 return JNI_TRUE;
587 }
588 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
589}
590
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800591static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592{
593 Vector<String8> locales;
594
595 AssetManager* am = assetManagerForJavaObject(env, clazz);
596 if (am == NULL) {
597 return NULL;
598 }
599
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800600 am->getLocales(&locales, includeSystemLocales);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601
602 const int N = locales.size();
603
604 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
605 if (result == NULL) {
606 return NULL;
607 }
608
609 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700610 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700611 if (str == NULL) {
612 return NULL;
613 }
614 env->SetObjectArrayElement(result, i, str);
615 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 }
617
618 return result;
619}
620
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800621static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
622{
623 return getLocales(env, clazz, true /* include system locales */);
624}
625
626static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
627{
628 return getLocales(env, clazz, false /* don't include system locales */);
629}
630
Filip Gruszczynski23493322015-07-29 17:02:59 -0700631static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
632 jobject result = env->NewObject(gConfigurationOffsets.classObject,
633 gConfigurationOffsets.constructor);
634 if (result == NULL) {
635 return NULL;
636 }
637
638 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
639 config.smallestScreenWidthDp);
640 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
641 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
642
643 return result;
644}
645
646static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
647 const Vector<ResTable_config>& configs) {
648 const int N = configs.size();
649 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
650 if (result == NULL) {
651 return NULL;
652 }
653
654 for (int i=0; i<N; i++) {
655 jobject config = constructConfigurationObject(env, configs[i]);
656 if (config == NULL) {
657 env->DeleteLocalRef(result);
658 return NULL;
659 }
660
661 env->SetObjectArrayElement(result, i, config);
662 env->DeleteLocalRef(config);
663 }
664
665 return result;
666}
667
668static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
669 AssetManager* am = assetManagerForJavaObject(env, clazz);
670 if (am == NULL) {
671 return NULL;
672 }
673
674 const ResTable& res(am->getResources());
675 Vector<ResTable_config> configs;
676 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
677
678 return getSizeConfigurationsInternal(env, configs);
679}
680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
682 jint mcc, jint mnc,
683 jstring locale, jint orientation,
684 jint touchscreen, jint density,
685 jint keyboard, jint keyboardHidden,
686 jint navigation,
687 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700688 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700689 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100690 jint screenLayout, jint uiMode,
691 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692{
693 AssetManager* am = assetManagerForJavaObject(env, clazz);
694 if (am == NULL) {
695 return;
696 }
697
698 ResTable_config config;
699 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700702
Adam Lesinski2738c962015-05-14 14:25:36 -0700703 // Constants duplicated from Java class android.content.res.Configuration.
704 static const jint kScreenLayoutRoundMask = 0x300;
705 static const jint kScreenLayoutRoundShift = 8;
706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 config.mcc = (uint16_t)mcc;
708 config.mnc = (uint16_t)mnc;
709 config.orientation = (uint8_t)orientation;
710 config.touchscreen = (uint8_t)touchscreen;
711 config.density = (uint16_t)density;
712 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700713 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 config.navigation = (uint8_t)navigation;
715 config.screenWidth = (uint16_t)screenWidth;
716 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700717 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700718 config.screenWidthDp = (uint16_t)screenWidthDp;
719 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700720 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100721 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 config.sdkVersion = (uint16_t)sdkVersion;
723 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700724
725 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
726 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
727 // into screenLayout2.
728 config.screenLayout2 =
729 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
734}
735
736static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
737 jstring name,
738 jstring defType,
739 jstring defPackage)
740{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700741 ScopedStringChars name16(env, name);
742 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 return 0;
744 }
745
746 AssetManager* am = assetManagerForJavaObject(env, clazz);
747 if (am == NULL) {
748 return 0;
749 }
750
Dan Albert66987492014-11-20 11:41:21 -0800751 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
752 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
753 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 jsize defTypeLen = defType
755 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800756 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
757 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
758 NULL))
759 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 jsize defPackageLen = defPackage
761 ? env->GetStringLength(defPackage) : 0;
762
763 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800764 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
765 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766
767 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800768 env->ReleaseStringChars(defPackage,
769 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 }
771 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800772 env->ReleaseStringChars(defType,
773 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775
776 return ident;
777}
778
779static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
780 jint resid)
781{
782 AssetManager* am = assetManagerForJavaObject(env, clazz);
783 if (am == NULL) {
784 return NULL;
785 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700788 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 return NULL;
790 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 String16 str;
793 if (name.package != NULL) {
794 str.setTo(name.package, name.packageLen);
795 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700796 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 if (str.size() > 0) {
798 char16_t div = ':';
799 str.append(&div, 1);
800 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700801 if (name.type8 != NULL) {
802 str.append(String16(name.type8, name.typeLen));
803 } else {
804 str.append(name.type, name.typeLen);
805 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700807 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 if (str.size() > 0) {
809 char16_t div = '/';
810 str.append(&div, 1);
811 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700812 if (name.name8 != NULL) {
813 str.append(String16(name.name8, name.nameLen));
814 } else {
815 str.append(name.name, name.nameLen);
816 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 return env->NewString((const jchar*)str.string(), str.size());
820}
821
822static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
823 jint resid)
824{
825 AssetManager* am = assetManagerForJavaObject(env, clazz);
826 if (am == NULL) {
827 return NULL;
828 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700831 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 return NULL;
833 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 if (name.package != NULL) {
836 return env->NewString((const jchar*)name.package, name.packageLen);
837 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 return NULL;
840}
841
842static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
843 jint resid)
844{
845 AssetManager* am = assetManagerForJavaObject(env, clazz);
846 if (am == NULL) {
847 return NULL;
848 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800850 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700851 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 return NULL;
853 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700854
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700855 if (name.type8 != NULL) {
856 return env->NewStringUTF(name.type8);
857 }
858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 if (name.type != NULL) {
860 return env->NewString((const jchar*)name.type, name.typeLen);
861 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 return NULL;
864}
865
866static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
867 jint resid)
868{
869 AssetManager* am = assetManagerForJavaObject(env, clazz);
870 if (am == NULL) {
871 return NULL;
872 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700875 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 return NULL;
877 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700878
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700879 if (name.name8 != NULL) {
880 return env->NewStringUTF(name.name8);
881 }
882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 if (name.name != NULL) {
884 return env->NewString((const jchar*)name.name, name.nameLen);
885 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 return NULL;
888}
889
890static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
891 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700892 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 jobject outValue,
894 jboolean resolve)
895{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800896 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800897 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700898 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800899 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 AssetManager* am = assetManagerForJavaObject(env, clazz);
901 if (am == NULL) {
902 return 0;
903 }
904 const ResTable& res(am->getResources());
905
906 Res_value value;
907 ResTable_config config;
908 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700909 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800910 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800911 if (block == BAD_INDEX) {
912 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
913 return 0;
914 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800915 }
916 uint32_t ref = ident;
917 if (resolve) {
918 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
919 if (kThrowOnBadId) {
920 if (block == BAD_INDEX) {
921 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
922 return 0;
923 }
924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800925 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000926 if (block >= 0) {
927 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
928 }
929
930 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931}
932
933static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
934 jint ident, jint bagEntryId,
935 jobject outValue, jboolean resolve)
936{
937 AssetManager* am = assetManagerForJavaObject(env, clazz);
938 if (am == NULL) {
939 return 0;
940 }
941 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943 // Now lock down the resource object and start pulling stuff from it.
944 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 ssize_t block = -1;
947 Res_value value;
948
949 const ResTable::bag_entry* entry = NULL;
950 uint32_t typeSpecFlags;
951 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
952
953 for (ssize_t i=0; i<entryCount; i++) {
954 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
955 block = entry->stringBlock;
956 value = entry->map.value;
957 }
958 entry++;
959 }
960
961 res.unlock();
962
963 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000964 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 uint32_t ref = ident;
968 if (resolve) {
969 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800970 if (kThrowOnBadId) {
971 if (block == BAD_INDEX) {
972 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
973 return 0;
974 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800975 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000977 if (block >= 0) {
978 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
979 }
980
981 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982}
983
984static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
985{
986 AssetManager* am = assetManagerForJavaObject(env, clazz);
987 if (am == NULL) {
988 return 0;
989 }
990 return am->getResources().getTableCount();
991}
992
Ashok Bhat896043d2014-01-17 16:02:38 +0000993static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 jint block)
995{
996 AssetManager* am = assetManagerForJavaObject(env, clazz);
997 if (am == NULL) {
998 return 0;
999 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001000 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001}
1002
1003static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
1004 jint cookie)
1005{
1006 AssetManager* am = assetManagerForJavaObject(env, clazz);
1007 if (am == NULL) {
1008 return NULL;
1009 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +00001010 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001012 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 return NULL;
1014 }
1015 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 return str;
1017}
1018
Adam Lesinskide898ff2014-01-29 18:20:45 -08001019static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1020{
1021 AssetManager* am = assetManagerForJavaObject(env, clazz);
1022 if (am == NULL) {
1023 return 0;
1024 }
1025
1026 const ResTable& res = am->getResources();
1027
1028 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1029 gSparseArrayOffsets.constructor);
1030 const size_t N = res.getBasePackageCount();
1031 for (size_t i = 0; i < N; i++) {
1032 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -08001033 env->CallVoidMethod(
1034 sparseArray, gSparseArrayOffsets.put,
1035 static_cast<jint>(res.getBasePackageId(i)),
1036 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1037 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -08001038 }
1039 return sparseArray;
1040}
1041
Ashok Bhat896043d2014-01-17 16:02:38 +00001042static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043{
1044 AssetManager* am = assetManagerForJavaObject(env, clazz);
1045 if (am == NULL) {
1046 return 0;
1047 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001048 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049}
1050
1051static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001052 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053{
Ashok Bhat896043d2014-01-17 16:02:38 +00001054 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 delete theme;
1056}
1057
1058static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001059 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 jint styleRes,
1061 jboolean force)
1062{
Ashok Bhat896043d2014-01-17 16:02:38 +00001063 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 theme->applyStyle(styleRes, force ? true : false);
1065}
1066
1067static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001068 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069{
Ashok Bhat896043d2014-01-17 16:02:38 +00001070 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1071 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 dest->setTo(*src);
1073}
1074
Alan Viverettee54d2452015-05-06 10:41:43 -07001075static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1076{
1077 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1078 theme->clear();
1079}
1080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001082 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083{
Ashok Bhat896043d2014-01-17 16:02:38 +00001084 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 const ResTable& res(theme->getResTable());
1086
1087 Res_value value;
1088 // XXX value could be different in different configs!
1089 uint32_t typeSpecFlags = 0;
1090 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1091 uint32_t ref = 0;
1092 if (resolve) {
1093 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001094 if (kThrowOnBadId) {
1095 if (block == BAD_INDEX) {
1096 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1097 return 0;
1098 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001099 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 }
1101 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1102}
1103
Alan Viverettec1d52792015-05-05 09:49:03 -07001104static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1105 jlong themeHandle)
1106{
1107 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1108 return theme->getChangingConfigurations();
1109}
1110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001112 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 jstring tag, jstring prefix)
1114{
Ashok Bhat896043d2014-01-17 16:02:38 +00001115 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001117 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 // XXX Need to use params.
1120 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121}
1122
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001123class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1124public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -07001125 explicit XmlAttributeFinder(const ResXMLParser* parser)
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001126 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1127 , mParser(parser) {}
1128
1129 inline uint32_t getAttribute(jsize index) const {
1130 return mParser->getAttributeNameResID(index);
1131 }
1132
1133private:
1134 const ResXMLParser* mParser;
1135};
1136
1137class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1138public:
1139 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1140 : BackTrackingAttributeFinder(start, end) {}
1141
1142 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1143 return entry->map.name.ident;
1144 }
1145};
1146
Alan Viverette52b999f2014-03-24 18:00:26 -07001147static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1148 jlong themeToken,
1149 jint defStyleAttr,
1150 jint defStyleRes,
1151 jintArray inValues,
1152 jintArray attrs,
1153 jintArray outValues,
1154 jintArray outIndices)
1155{
1156 if (themeToken == 0) {
1157 jniThrowNullPointerException(env, "theme token");
1158 return JNI_FALSE;
1159 }
1160 if (attrs == NULL) {
1161 jniThrowNullPointerException(env, "attrs");
1162 return JNI_FALSE;
1163 }
1164 if (outValues == NULL) {
1165 jniThrowNullPointerException(env, "out values");
1166 return JNI_FALSE;
1167 }
1168
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001169 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001170 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1171 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001172 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001173
1174 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1175 const ResTable& res = theme->getResTable();
1176 ResTable_config config;
1177 Res_value value;
1178
1179 const jsize NI = env->GetArrayLength(attrs);
1180 const jsize NV = env->GetArrayLength(outValues);
1181 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1182 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1183 return JNI_FALSE;
1184 }
1185
1186 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1187 if (src == NULL) {
1188 return JNI_FALSE;
1189 }
1190
1191 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1192 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1193
1194 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1195 jint* dest = baseDest;
1196 if (dest == NULL) {
1197 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1198 return JNI_FALSE;
1199 }
1200
1201 jint* indices = NULL;
1202 int indicesIdx = 0;
1203 if (outIndices != NULL) {
1204 if (env->GetArrayLength(outIndices) > NI) {
1205 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1206 }
1207 }
1208
1209 // Load default style from attribute, if specified...
1210 uint32_t defStyleBagTypeSetFlags = 0;
1211 if (defStyleAttr != 0) {
1212 Res_value value;
1213 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1214 if (value.dataType == Res_value::TYPE_REFERENCE) {
1215 defStyleRes = value.data;
1216 }
1217 }
1218 }
1219
1220 // Now lock down the resource object and start pulling stuff from it.
1221 res.lock();
1222
1223 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001224 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001225 uint32_t defStyleTypeSetFlags = 0;
1226 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001227 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001228 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001229 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1230 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001231
1232 // Now iterate through all of the attributes that the client has requested,
1233 // filling in each with whatever data we can find.
1234 ssize_t block = 0;
1235 uint32_t typeSetFlags;
1236 for (jsize ii=0; ii<NI; ii++) {
1237 const uint32_t curIdent = (uint32_t)src[ii];
1238
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001239 if (kDebugStyles) {
1240 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1241 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001242
1243 // Try to find a value for this attribute... we prioritize values
1244 // coming from, first XML attributes, then XML style, then default
1245 // style, and finally the theme.
1246 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001247 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001248 typeSetFlags = 0;
1249 config.density = 0;
1250
1251 // Retrieve the current input value if available.
1252 if (NSV > 0 && srcValues[ii] != 0) {
1253 block = -1;
1254 value.dataType = Res_value::TYPE_ATTRIBUTE;
1255 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001256 if (kDebugStyles) {
1257 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1258 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001259 }
1260
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001261 if (value.dataType == Res_value::TYPE_NULL) {
1262 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1263 if (defStyleEntry != defStyleEnd) {
1264 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001265 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001266 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001267 if (kDebugStyles) {
1268 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1269 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001270 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001271 }
1272
1273 uint32_t resid = 0;
1274 if (value.dataType != Res_value::TYPE_NULL) {
1275 // Take care of resolving the found resource to its final value.
1276 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1277 &resid, &typeSetFlags, &config);
1278 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001279 if (kDebugStyles) {
1280 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1281 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001282 } else {
1283 // If we still don't have a value for this attribute, try to find
1284 // it in the theme!
1285 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1286 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001287 if (kDebugStyles) {
1288 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1289 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001290 newBlock = res.resolveReference(&value, block, &resid,
1291 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001292 if (kThrowOnBadId) {
1293 if (newBlock == BAD_INDEX) {
1294 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1295 return JNI_FALSE;
1296 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001297 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001298 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001299 if (kDebugStyles) {
1300 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1301 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001302 }
1303 }
1304
1305 // Deal with the special @null value -- it turns back to TYPE_NULL.
1306 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001307 if (kDebugStyles) {
1308 ALOGI("-> Setting to @null!");
1309 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001310 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001311 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001312 block = -1;
1313 }
1314
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001315 if (kDebugStyles) {
1316 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1317 value.data);
1318 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001319
1320 // Write the final value back to Java.
1321 dest[STYLE_TYPE] = value.dataType;
1322 dest[STYLE_DATA] = value.data;
1323 dest[STYLE_ASSET_COOKIE] =
1324 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1325 dest[STYLE_RESOURCE_ID] = resid;
1326 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1327 dest[STYLE_DENSITY] = config.density;
1328
1329 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1330 indicesIdx++;
1331 indices[indicesIdx] = ii;
1332 }
1333
1334 dest += STYLE_NUM_ENTRIES;
1335 }
1336
1337 res.unlock();
1338
1339 if (indices != NULL) {
1340 indices[0] = indicesIdx;
1341 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1342 }
1343 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1344 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1345 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1346
1347 return JNI_TRUE;
1348}
1349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001351 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 jint defStyleAttr,
1353 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001354 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 jintArray attrs,
1356 jintArray outValues,
1357 jintArray outIndices)
1358{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001359 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001360 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001361 return JNI_FALSE;
1362 }
1363 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001364 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001365 return JNI_FALSE;
1366 }
1367 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001368 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 return JNI_FALSE;
1370 }
1371
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001372 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001373 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1374 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1375 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001376 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001377
Ashok Bhat896043d2014-01-17 16:02:38 +00001378 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001380 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001381 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 Res_value value;
1383
1384 const jsize NI = env->GetArrayLength(attrs);
1385 const jsize NV = env->GetArrayLength(outValues);
1386 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001387 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 return JNI_FALSE;
1389 }
1390
1391 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1392 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393 return JNI_FALSE;
1394 }
1395
1396 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1397 jint* dest = baseDest;
1398 if (dest == NULL) {
1399 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 return JNI_FALSE;
1401 }
1402
1403 jint* indices = NULL;
1404 int indicesIdx = 0;
1405 if (outIndices != NULL) {
1406 if (env->GetArrayLength(outIndices) > NI) {
1407 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1408 }
1409 }
1410
1411 // Load default style from attribute, if specified...
1412 uint32_t defStyleBagTypeSetFlags = 0;
1413 if (defStyleAttr != 0) {
1414 Res_value value;
1415 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1416 if (value.dataType == Res_value::TYPE_REFERENCE) {
1417 defStyleRes = value.data;
1418 }
1419 }
1420 }
1421
1422 // Retrieve the style class associated with the current XML tag.
1423 int style = 0;
1424 uint32_t styleBagTypeSetFlags = 0;
1425 if (xmlParser != NULL) {
1426 ssize_t idx = xmlParser->indexOfStyle();
1427 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1428 if (value.dataType == value.TYPE_ATTRIBUTE) {
1429 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1430 value.dataType = Res_value::TYPE_NULL;
1431 }
1432 }
1433 if (value.dataType == value.TYPE_REFERENCE) {
1434 style = value.data;
1435 }
1436 }
1437 }
1438
1439 // Now lock down the resource object and start pulling stuff from it.
1440 res.lock();
1441
1442 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001443 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 uint32_t defStyleTypeSetFlags = 0;
1445 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001446 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001447 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001448 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1449 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450
1451 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001452 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001454 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001456 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1457 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458
1459 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001461 XmlAttributeFinder xmlAttrFinder(xmlParser);
1462 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463
1464 // Now iterate through all of the attributes that the client has requested,
1465 // filling in each with whatever data we can find.
1466 ssize_t block = 0;
1467 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001468 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 const uint32_t curIdent = (uint32_t)src[ii];
1470
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001471 if (kDebugStyles) {
1472 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1473 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 // Try to find a value for this attribute... we prioritize values
1476 // coming from, first XML attributes, then XML style, then default
1477 // style, and finally the theme.
1478 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001479 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001481 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001483 // Walk through the xml attributes looking for the requested attribute.
1484 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1485 if (xmlAttrIdx != xmlAttrEnd) {
1486 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001488 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001489 if (kDebugStyles) {
1490 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 }
1493
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001494 if (value.dataType == Res_value::TYPE_NULL) {
1495 // Walk through the style class values looking for the requested attribute.
1496 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1497 if (styleAttrEntry != styleAttrEnd) {
1498 // We found the attribute we were looking for.
1499 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001501 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001502 if (kDebugStyles) {
1503 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1504 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 }
1507
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001508 if (value.dataType == Res_value::TYPE_NULL) {
1509 // Walk through the default style values looking for the requested attribute.
1510 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1511 if (defStyleAttrEntry != defStyleAttrEnd) {
1512 // We found the attribute we were looking for.
1513 block = defStyleAttrEntry->stringBlock;
1514 typeSetFlags = styleTypeSetFlags;
1515 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001516 if (kDebugStyles) {
1517 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522 uint32_t resid = 0;
1523 if (value.dataType != Res_value::TYPE_NULL) {
1524 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001525 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1526 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001527 if (newBlock >= 0) {
1528 block = newBlock;
1529 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001530
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001531 if (kDebugStyles) {
1532 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1533 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 } else {
1535 // If we still don't have a value for this attribute, try to find
1536 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1538 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001539 if (kDebugStyles) {
1540 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1541 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001542 newBlock = res.resolveReference(&value, block, &resid,
1543 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001544 if (kThrowOnBadId) {
1545 if (newBlock == BAD_INDEX) {
1546 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1547 return JNI_FALSE;
1548 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001549 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001550
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001551 if (newBlock >= 0) {
1552 block = newBlock;
1553 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001554
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001555 if (kDebugStyles) {
1556 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
1559 }
1560
1561 // Deal with the special @null value -- it turns back to TYPE_NULL.
1562 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001563 if (kDebugStyles) {
1564 ALOGI("-> Setting to @null!");
1565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001567 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001568 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 }
1570
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001571 if (kDebugStyles) {
1572 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574
1575 // Write the final value back to Java.
1576 dest[STYLE_TYPE] = value.dataType;
1577 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001578 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1579 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 dest[STYLE_RESOURCE_ID] = resid;
1581 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001582 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1585 indicesIdx++;
1586 indices[indicesIdx] = ii;
1587 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 dest += STYLE_NUM_ENTRIES;
1590 }
1591
1592 res.unlock();
1593
1594 if (indices != NULL) {
1595 indices[0] = indicesIdx;
1596 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1597 }
1598 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1599 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1600
1601 return JNI_TRUE;
1602}
1603
1604static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001605 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 jintArray attrs,
1607 jintArray outValues,
1608 jintArray outIndices)
1609{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001610 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001611 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001612 return JNI_FALSE;
1613 }
1614 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001615 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001616 return JNI_FALSE;
1617 }
1618 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001619 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 return JNI_FALSE;
1621 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 AssetManager* am = assetManagerForJavaObject(env, clazz);
1624 if (am == NULL) {
1625 return JNI_FALSE;
1626 }
1627 const ResTable& res(am->getResources());
1628 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001629 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 const jsize NI = env->GetArrayLength(attrs);
1633 const jsize NV = env->GetArrayLength(outValues);
1634 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001635 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 return JNI_FALSE;
1637 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1640 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 return JNI_FALSE;
1642 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1645 jint* dest = baseDest;
1646 if (dest == NULL) {
1647 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 return JNI_FALSE;
1649 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 jint* indices = NULL;
1652 int indicesIdx = 0;
1653 if (outIndices != NULL) {
1654 if (env->GetArrayLength(outIndices) > NI) {
1655 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1656 }
1657 }
1658
1659 // Now lock down the resource object and start pulling stuff from it.
1660 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 // Retrieve the XML attributes, if requested.
1663 const jsize NX = xmlParser->getAttributeCount();
1664 jsize ix=0;
1665 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669 // Now iterate through all of the attributes that the client has requested,
1670 // filling in each with whatever data we can find.
1671 ssize_t block = 0;
1672 uint32_t typeSetFlags;
1673 for (jsize ii=0; ii<NI; ii++) {
1674 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 // Try to find a value for this attribute...
1677 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001678 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001680 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001683 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 ix++;
1685 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1686 }
1687 // Retrieve the current XML attribute if it matches, and step to next.
1688 if (ix < NX && curIdent == curXmlAttr) {
1689 block = kXmlBlock;
1690 xmlParser->getAttributeValue(ix, &value);
1691 ix++;
1692 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1693 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1696 uint32_t resid = 0;
1697 if (value.dataType != Res_value::TYPE_NULL) {
1698 // Take care of resolving the found resource to its final value.
1699 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001700 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1701 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001702 if (kThrowOnBadId) {
1703 if (newBlock == BAD_INDEX) {
1704 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1705 return JNI_FALSE;
1706 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 if (newBlock >= 0) block = newBlock;
1709 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 // Deal with the special @null value -- it turns back to TYPE_NULL.
1712 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1713 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001714 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 // Write the final value back to Java.
1720 dest[STYLE_TYPE] = value.dataType;
1721 dest[STYLE_DATA] = value.data;
1722 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001723 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 dest[STYLE_RESOURCE_ID] = resid;
1725 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001726 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1729 indicesIdx++;
1730 indices[indicesIdx] = ii;
1731 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 dest += STYLE_NUM_ENTRIES;
1734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 if (indices != NULL) {
1739 indices[0] = indicesIdx;
1740 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1741 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1744 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 return JNI_TRUE;
1747}
1748
1749static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1750 jint id)
1751{
1752 AssetManager* am = assetManagerForJavaObject(env, clazz);
1753 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001754 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 }
1756 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 res.lock();
1759 const ResTable::bag_entry* defStyleEnt = NULL;
1760 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1761 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001762
Ashok Bhat896043d2014-01-17 16:02:38 +00001763 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764}
1765
1766static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1767 jint id,
1768 jintArray outValues)
1769{
1770 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001771 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 return JNI_FALSE;
1773 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 AssetManager* am = assetManagerForJavaObject(env, clazz);
1776 if (am == NULL) {
1777 return JNI_FALSE;
1778 }
1779 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001780 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001781 Res_value value;
1782 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1787 jint* dest = baseDest;
1788 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001789 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 return JNI_FALSE;
1791 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001793 // Now lock down the resource object and start pulling stuff from it.
1794 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 const ResTable::bag_entry* arrayEnt = NULL;
1797 uint32_t arrayTypeSetFlags = 0;
1798 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1799 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1800 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 int i = 0;
1803 uint32_t typeSetFlags;
1804 while (i < NV && arrayEnt < endArrayEnt) {
1805 block = arrayEnt->stringBlock;
1806 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001807 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 uint32_t resid = 0;
1811 if (value.dataType != Res_value::TYPE_NULL) {
1812 // Take care of resolving the found resource to its final value.
1813 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001814 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1815 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001816 if (kThrowOnBadId) {
1817 if (newBlock == BAD_INDEX) {
1818 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1819 return JNI_FALSE;
1820 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 if (newBlock >= 0) block = newBlock;
1823 }
1824
1825 // Deal with the special @null value -- it turns back to TYPE_NULL.
1826 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1827 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001828 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 }
1830
1831 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1832
1833 // Write the final value back to Java.
1834 dest[STYLE_TYPE] = value.dataType;
1835 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001836 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 dest[STYLE_RESOURCE_ID] = resid;
1838 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001839 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 dest += STYLE_NUM_ENTRIES;
1841 i+= STYLE_NUM_ENTRIES;
1842 arrayEnt++;
1843 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001851 return i;
1852}
1853
Ashok Bhat896043d2014-01-17 16:02:38 +00001854static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 jint cookie,
1856 jstring fileName)
1857{
1858 AssetManager* am = assetManagerForJavaObject(env, clazz);
1859 if (am == NULL) {
1860 return 0;
1861 }
1862
Steve Block71f2cf12011-10-20 11:56:00 +01001863 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864
Elliott Hughes69a017b2011-04-08 14:10:28 -07001865 ScopedUtfChars fileName8(env, fileName);
1866 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 return 0;
1868 }
1869
Adam Lesinskide898ff2014-01-29 18:20:45 -08001870 int32_t assetCookie = static_cast<int32_t>(cookie);
1871 Asset* a = assetCookie
1872 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1873 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874
1875 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001876 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 return 0;
1878 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879
Adam Lesinskide898ff2014-01-29 18:20:45 -08001880 const DynamicRefTable* dynamicRefTable =
1881 am->getResources().getDynamicRefTableForCookie(assetCookie);
1882 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1884 a->close();
1885 delete a;
1886
1887 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001888 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001889 return 0;
1890 }
1891
Ashok Bhat896043d2014-01-17 16:02:38 +00001892 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893}
1894
1895static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1896 jint arrayResId)
1897{
1898 AssetManager* am = assetManagerForJavaObject(env, clazz);
1899 if (am == NULL) {
1900 return NULL;
1901 }
1902 const ResTable& res(am->getResources());
1903
1904 const ResTable::bag_entry* startOfBag;
1905 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1906 if (N < 0) {
1907 return NULL;
1908 }
1909
1910 jintArray array = env->NewIntArray(N * 2);
1911 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 res.unlockBag(startOfBag);
1913 return NULL;
1914 }
1915
1916 Res_value value;
1917 const ResTable::bag_entry* bag = startOfBag;
1918 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1919 jint stringIndex = -1;
1920 jint stringBlock = 0;
1921 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 // Take care of resolving the found resource to its final value.
1924 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1925 if (value.dataType == Res_value::TYPE_STRING) {
1926 stringIndex = value.data;
1927 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001928
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001929 if (kThrowOnBadId) {
1930 if (stringBlock == BAD_INDEX) {
1931 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1932 return array;
1933 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001934 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 //todo: It might be faster to allocate a C array to contain
1937 // the blocknums and indices, put them in there and then
1938 // do just one SetIntArrayRegion()
1939 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1940 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1941 j = j + 2;
1942 }
1943 res.unlockBag(startOfBag);
1944 return array;
1945}
1946
1947static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1948 jint arrayResId)
1949{
1950 AssetManager* am = assetManagerForJavaObject(env, clazz);
1951 if (am == NULL) {
1952 return NULL;
1953 }
1954 const ResTable& res(am->getResources());
1955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 const ResTable::bag_entry* startOfBag;
1957 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1958 if (N < 0) {
1959 return NULL;
1960 }
1961
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001962 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001963 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 res.unlockBag(startOfBag);
1965 return NULL;
1966 }
1967
1968 Res_value value;
1969 const ResTable::bag_entry* bag = startOfBag;
1970 size_t strLen = 0;
1971 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1972 value = bag->map.value;
1973 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 // Take care of resolving the found resource to its final value.
1976 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001977 if (kThrowOnBadId) {
1978 if (block == BAD_INDEX) {
1979 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1980 return array;
1981 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001984 const ResStringPool* pool = res.getTableStringBlock(block);
1985 const char* str8 = pool->string8At(value.data, &strLen);
1986 if (str8 != NULL) {
1987 str = env->NewStringUTF(str8);
1988 } else {
1989 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001990 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1991 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001992 }
1993
1994 // If one of our NewString{UTF} calls failed due to memory, an
1995 // exception will be pending.
1996 if (env->ExceptionCheck()) {
1997 res.unlockBag(startOfBag);
1998 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 }
Kenny Root780d2a12010-02-22 22:36:26 -08002000
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002001 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07002002
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002003 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
2004 // If we have a large amount of strings in our array, we might
2005 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07002006 env->DeleteLocalRef(str);
2007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 }
2009 res.unlockBag(startOfBag);
2010 return array;
2011}
2012
2013static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
2014 jint arrayResId)
2015{
2016 AssetManager* am = assetManagerForJavaObject(env, clazz);
2017 if (am == NULL) {
2018 return NULL;
2019 }
2020 const ResTable& res(am->getResources());
2021
2022 const ResTable::bag_entry* startOfBag;
2023 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
2024 if (N < 0) {
2025 return NULL;
2026 }
2027
2028 jintArray array = env->NewIntArray(N);
2029 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 res.unlockBag(startOfBag);
2031 return NULL;
2032 }
2033
2034 Res_value value;
2035 const ResTable::bag_entry* bag = startOfBag;
2036 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2037 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07002038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 // Take care of resolving the found resource to its final value.
2040 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08002041 if (kThrowOnBadId) {
2042 if (block == BAD_INDEX) {
2043 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
2044 return array;
2045 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002046 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 if (value.dataType >= Res_value::TYPE_FIRST_INT
2048 && value.dataType <= Res_value::TYPE_LAST_INT) {
2049 int intVal = value.data;
2050 env->SetIntArrayRegion(array, i, 1, &intVal);
2051 }
2052 }
2053 res.unlockBag(startOfBag);
2054 return array;
2055}
2056
Jon Miranda042ad632014-09-03 17:57:35 -07002057static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
2058 jint styleId)
2059{
2060 AssetManager* am = assetManagerForJavaObject(env, clazz);
2061 if (am == NULL) {
2062 return NULL;
2063 }
2064 const ResTable& res(am->getResources());
2065
2066 const ResTable::bag_entry* startOfBag;
2067 const ssize_t N = res.lockBag(styleId, &startOfBag);
2068 if (N < 0) {
2069 return NULL;
2070 }
2071
2072 jintArray array = env->NewIntArray(N);
2073 if (array == NULL) {
2074 res.unlockBag(startOfBag);
2075 return NULL;
2076 }
2077
Jon Miranda042ad632014-09-03 17:57:35 -07002078 const ResTable::bag_entry* bag = startOfBag;
2079 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2080 int resourceId = bag->map.name.ident;
2081 env->SetIntArrayRegion(array, i, 1, &resourceId);
2082 }
2083 res.unlockBag(startOfBag);
2084 return array;
2085}
2086
Mårten Kongstad48d22322014-01-31 14:43:27 +01002087static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002089 if (isSystem) {
2090 verifySystemIdmaps();
2091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 AssetManager* am = new AssetManager();
2093 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002094 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 return;
2096 }
2097
2098 am->addDefaultAssets();
2099
Steve Block71f2cf12011-10-20 11:56:00 +01002100 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002101 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102}
2103
2104static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2105{
2106 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002107 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002108 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 if (am != NULL) {
2110 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002111 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 }
2113}
2114
2115static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2116{
2117 return Asset::getGlobalCount();
2118}
2119
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002120static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2121{
2122 String8 alloc = Asset::getAssetAllocations();
2123 if (alloc.length() <= 0) {
2124 return NULL;
2125 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002126
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002127 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002128 return str;
2129}
2130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2132{
2133 return AssetManager::getGlobalCount();
2134}
2135
2136// ----------------------------------------------------------------------------
2137
2138/*
2139 * JNI registration.
2140 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002141static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 /* name, signature, funcPtr */
2143
2144 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002145 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 (void*) android_content_AssetManager_openAsset },
2147 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2148 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002149 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 (void*) android_content_AssetManager_openNonAssetNative },
2151 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2152 (void*) android_content_AssetManager_openNonAssetFdNative },
2153 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2154 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002155 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002157 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002159 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002161 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 (void*) android_content_AssetManager_seekAsset },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002163 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164 (void*) android_content_AssetManager_getAssetLength },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002165 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 (void*) android_content_AssetManager_getAssetRemainingLength },
Tao Baia6d7e3f2015-09-01 18:49:54 -07002167 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002169 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002170 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 { "isUpToDate", "()Z",
2172 (void*) android_content_AssetManager_isUpToDate },
2173
2174 // Resources.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 { "getLocales", "()[Ljava/lang/String;",
2176 (void*) android_content_AssetManager_getLocales },
Roozbeh Pournader1c686f22015-12-18 14:22:14 -08002177 { "getNonSystemLocales", "()[Ljava/lang/String;",
2178 (void*) android_content_AssetManager_getNonSystemLocales },
Filip Gruszczynski23493322015-07-29 17:02:59 -07002179 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
2180 (void*) android_content_AssetManager_getSizeConfigurations },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002181 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002182 (void*) android_content_AssetManager_setConfiguration },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002183 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 (void*) android_content_AssetManager_getResourceIdentifier },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002185 { "getResourceName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 (void*) android_content_AssetManager_getResourceName },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002187 { "getResourcePackageName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 (void*) android_content_AssetManager_getResourcePackageName },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002189 { "getResourceTypeName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 (void*) android_content_AssetManager_getResourceTypeName },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002191 { "getResourceEntryName","(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 (void*) android_content_AssetManager_getResourceEntryName },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002193 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194 (void*) android_content_AssetManager_loadResourceValue },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002195 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 (void*) android_content_AssetManager_loadResourceBagValue },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002197 { "getStringBlockCount","()I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 (void*) android_content_AssetManager_getStringBlockCount },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002199 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 (void*) android_content_AssetManager_getNativeStringBlock },
2201 { "getCookieName","(I)Ljava/lang/String;",
2202 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002203 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2204 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002205
2206 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002207 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002209 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002211 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002213 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002215 { "clearTheme", "(J)V",
2216 (void*) android_content_AssetManager_clearTheme },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002217 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002218 (void*) android_content_AssetManager_loadThemeAttributeValue },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002219 { "getThemeChangingConfigurations", "(J)I",
Alan Viverettec1d52792015-05-05 09:49:03 -07002220 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002221 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 (void*) android_content_AssetManager_dumpTheme },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002223 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002224 (void*) android_content_AssetManager_applyStyle },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002225 { "resolveAttrs","(JII[I[I[I[I)Z",
Alan Viverette607bd842014-09-12 12:36:35 -07002226 (void*) android_content_AssetManager_resolveAttrs },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002227 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 (void*) android_content_AssetManager_retrieveAttributes },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002229 { "getArraySize","(I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 (void*) android_content_AssetManager_getArraySize },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002231 { "retrieveArray","(I[I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232 (void*) android_content_AssetManager_retrieveArray },
2233
2234 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002235 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002236 (void*) android_content_AssetManager_openXmlAssetNative },
2237
2238 // Arrays.
2239 { "getArrayStringResource","(I)[Ljava/lang/String;",
2240 (void*) android_content_AssetManager_getArrayStringResource },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002241 { "getArrayStringInfo","(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 (void*) android_content_AssetManager_getArrayStringInfo },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002243 { "getArrayIntResource","(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002244 (void*) android_content_AssetManager_getArrayIntResource },
Tim Zhang14e0a1e2017-02-16 09:55:27 +08002245 { "getStyleAttributes","(I)[I",
Jon Miranda042ad632014-09-03 17:57:35 -07002246 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247
2248 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002249 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 (void*) android_content_AssetManager_init },
2251 { "destroy", "()V",
2252 (void*) android_content_AssetManager_destroy },
2253 { "getGlobalAssetCount", "()I",
2254 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002255 { "getAssetAllocations", "()Ljava/lang/String;",
2256 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002258 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259};
2260
2261int register_android_content_AssetManager(JNIEnv* env)
2262{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002263 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2264 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2265 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2266 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2267 "Ljava/lang/CharSequence;");
2268 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2269 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2270 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2271 "changingConfigurations", "I");
2272 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273
Andreas Gampe987f79f2014-11-18 17:29:46 -08002274 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2275 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2276 "Landroid/os/ParcelFileDescriptor;");
2277 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2278 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279
Andreas Gampe987f79f2014-11-18 17:29:46 -08002280 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2281 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282
Andreas Gampe987f79f2014-11-18 17:29:46 -08002283 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2284 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002285
Andreas Gampe987f79f2014-11-18 17:29:46 -08002286 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2287 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2288 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2289 "<init>", "()V");
2290 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2291 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002292
Filip Gruszczynski23493322015-07-29 17:02:59 -07002293 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
2294 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
2295 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
2296 "<init>", "()V");
2297 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2298 "smallestScreenWidthDp", "I");
2299 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2300 "screenWidthDp", "I");
2301 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
2302 "screenHeightDp", "I");
2303
Andreas Gampe987f79f2014-11-18 17:29:46 -08002304 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2305 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002306}
2307
2308}; // namespace android