blob: 90606a35b5a2d899afdc653732277b6b39b6b6f4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
20#include <android_runtime/android_util_AssetManager.h>
21
Dan Albert46d84442014-11-18 16:07:51 -080022#include <inttypes.h>
23#include <linux/capability.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010025#include <sys/types.h>
26#include <sys/wait.h>
Mårten Kongstad83ab0d72015-03-20 12:57:36 +010027#include <sys/stat.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010028
Dan Albert46d84442014-11-18 16:07:51 -080029#include <private/android_filesystem_config.h> // for AID_SYSTEM
30
Dan Albert3a091b72014-11-20 15:41:25 -080031#include "androidfw/Asset.h"
32#include "androidfw/AssetManager.h"
33#include "androidfw/AttributeFinder.h"
34#include "androidfw/ResourceTypes.h"
35#include "android_runtime/AndroidRuntime.h"
36#include "android_util_Binder.h"
37#include "core_jni_helpers.h"
38#include "jni.h"
Dan Albert46d84442014-11-18 16:07:51 -080039#include "JNIHelp.h"
40#include "ScopedStringChars.h"
41#include "ScopedUtfChars.h"
Dan Albert46d84442014-11-18 16:07:51 -080042#include "utils/Log.h"
43#include "utils/misc.h"
44
Mårten Kongstad48d22322014-01-31 14:43:27 +010045extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
46extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
47
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
49namespace android {
50
Andreas Gampe0f0b4912014-11-12 08:03:48 -080051static const bool kThrowOnBadId = false;
52static const bool kDebugStyles = false;
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054// ----------------------------------------------------------------------------
55
56static struct typedvalue_offsets_t
57{
58 jfieldID mType;
59 jfieldID mData;
60 jfieldID mString;
61 jfieldID mAssetCookie;
62 jfieldID mResourceId;
63 jfieldID mChangingConfigurations;
64 jfieldID mDensity;
65} gTypedValueOffsets;
66
67static struct assetfiledescriptor_offsets_t
68{
69 jfieldID mFd;
70 jfieldID mStartOffset;
71 jfieldID mLength;
72} gAssetFileDescriptorOffsets;
73
74static struct assetmanager_offsets_t
75{
76 jfieldID mObject;
77} gAssetManagerOffsets;
78
Adam Lesinskide898ff2014-01-29 18:20:45 -080079static struct sparsearray_offsets_t
80{
81 jclass classObject;
82 jmethodID constructor;
83 jmethodID put;
84} gSparseArrayOffsets;
85
Filip Gruszczynski23493322015-07-29 17:02:59 -070086static struct configuration_offsets_t
87{
88 jclass classObject;
89 jmethodID constructor;
90 jfieldID mSmallestScreenWidthDpOffset;
91 jfieldID mScreenWidthDpOffset;
92 jfieldID mScreenHeightDpOffset;
93} gConfigurationOffsets;
94
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095jclass g_stringClass = NULL;
96
97// ----------------------------------------------------------------------------
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700100 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 STYLE_TYPE = 0,
102 STYLE_DATA = 1,
103 STYLE_ASSET_COOKIE = 2,
104 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700105 STYLE_CHANGING_CONFIGURATIONS = 4,
106 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107};
108
109static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
110 const Res_value& value, uint32_t ref, ssize_t block,
111 uint32_t typeSpecFlags, ResTable_config* config = NULL);
112
113jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
114 const Res_value& value, uint32_t ref, ssize_t block,
115 uint32_t typeSpecFlags, ResTable_config* config)
116{
117 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
118 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000119 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
121 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
122 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
123 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
124 typeSpecFlags);
125 if (config != NULL) {
126 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
127 }
128 return block;
129}
130
Mårten Kongstad48d22322014-01-31 14:43:27 +0100131// This is called by zygote (running as user root) as part of preloadResources.
132static void verifySystemIdmaps()
133{
134 pid_t pid;
135 char system_id[10];
136
137 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
138
139 switch (pid = fork()) {
140 case -1:
141 ALOGE("failed to fork for idmap: %s", strerror(errno));
142 break;
143 case 0: // child
144 {
145 struct __user_cap_header_struct capheader;
146 struct __user_cap_data_struct capdata;
147
148 memset(&capheader, 0, sizeof(capheader));
149 memset(&capdata, 0, sizeof(capdata));
150
151 capheader.version = _LINUX_CAPABILITY_VERSION;
152 capheader.pid = 0;
153
154 if (capget(&capheader, &capdata) != 0) {
155 ALOGE("capget: %s\n", strerror(errno));
156 exit(1);
157 }
158
159 capdata.effective = capdata.permitted;
160 if (capset(&capheader, &capdata) != 0) {
161 ALOGE("capset: %s\n", strerror(errno));
162 exit(1);
163 }
164
165 if (setgid(AID_SYSTEM) != 0) {
166 ALOGE("setgid: %s\n", strerror(errno));
167 exit(1);
168 }
169
170 if (setuid(AID_SYSTEM) != 0) {
171 ALOGE("setuid: %s\n", strerror(errno));
172 exit(1);
173 }
174
Mårten Kongstad83ab0d72015-03-20 12:57:36 +0100175 // Generic idmap parameters
176 const char* argv[7];
177 int argc = 0;
178 struct stat st;
179
180 memset(argv, NULL, sizeof(argv));
181 argv[argc++] = AssetManager::IDMAP_BIN;
182 argv[argc++] = "--scan";
183 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
184 argv[argc++] = AssetManager::TARGET_APK_PATH;
185 argv[argc++] = AssetManager::IDMAP_DIR;
186
187 // Directories to scan for overlays
188 // /vendor/overlay
189 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
190 argv[argc++] = AssetManager::OVERLAY_DIR;
191 }
192
193 // Finally, invoke idmap (if any overlay directory exists)
194 if (argc > 5) {
195 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
196 ALOGE("failed to execl for idmap: %s", strerror(errno));
197 exit(1); // should never get here
198 } else {
199 exit(0);
200 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100201 }
202 break;
203 default: // parent
204 waitpid(pid, NULL, 0);
205 break;
206 }
207}
208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209// ----------------------------------------------------------------------------
210
211// this guy is exported to other jni routines
212AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
213{
Ashok Bhat896043d2014-01-17 16:02:38 +0000214 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
215 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 if (am != NULL) {
217 return am;
218 }
219 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
220 return NULL;
221}
222
Ashok Bhat896043d2014-01-17 16:02:38 +0000223static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 jstring fileName, jint mode)
225{
226 AssetManager* am = assetManagerForJavaObject(env, clazz);
227 if (am == NULL) {
228 return 0;
229 }
230
Steve Block71f2cf12011-10-20 11:56:00 +0100231 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
Elliott Hughes69a017b2011-04-08 14:10:28 -0700233 ScopedUtfChars fileName8(env, fileName);
234 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000235 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 return -1;
237 }
238
239 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
240 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700241 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 return -1;
243 }
244
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246
247 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700248 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 return -1;
250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251
252 //printf("Created Asset Stream: %p\n", a);
253
Ashok Bhat896043d2014-01-17 16:02:38 +0000254 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255}
256
257static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
258{
Kenny Rootddb76c42010-11-24 12:56:06 -0800259 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 int fd = a->openFileDescriptor(&startOffset, &length);
261 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700264 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 "This file can not be opened as a file descriptor; it is probably compressed");
266 return NULL;
267 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
270 if (offsets == NULL) {
271 close(fd);
272 return NULL;
273 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 offsets[0] = startOffset;
276 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700279
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700280 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 if (fileDesc == NULL) {
282 close(fd);
283 return NULL;
284 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 return newParcelFileDescriptor(env, fileDesc);
287}
288
289static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
290 jstring fileName, jlongArray outOffsets)
291{
292 AssetManager* am = assetManagerForJavaObject(env, clazz);
293 if (am == NULL) {
294 return NULL;
295 }
296
Steve Block71f2cf12011-10-20 11:56:00 +0100297 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298
Elliott Hughes69a017b2011-04-08 14:10:28 -0700299 ScopedUtfChars fileName8(env, fileName);
300 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 return NULL;
302 }
303
Elliott Hughes69a017b2011-04-08 14:10:28 -0700304 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
306 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700307 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 return NULL;
309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 //printf("Created Asset Stream: %p\n", a);
312
313 return returnParcelFileDescriptor(env, a, outOffsets);
314}
315
Ashok Bhat896043d2014-01-17 16:02:38 +0000316static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 jint cookie,
318 jstring fileName,
319 jint mode)
320{
321 AssetManager* am = assetManagerForJavaObject(env, clazz);
322 if (am == NULL) {
323 return 0;
324 }
325
Steve Block71f2cf12011-10-20 11:56:00 +0100326 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327
Elliott Hughes69a017b2011-04-08 14:10:28 -0700328 ScopedUtfChars fileName8(env, fileName);
329 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 return -1;
331 }
332
333 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
334 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700335 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 return -1;
337 }
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000340 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
341 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700342 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
344 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700345 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return -1;
347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348
349 //printf("Created Asset Stream: %p\n", a);
350
Ashok Bhat896043d2014-01-17 16:02:38 +0000351 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352}
353
354static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
355 jint cookie,
356 jstring fileName,
357 jlongArray outOffsets)
358{
359 AssetManager* am = assetManagerForJavaObject(env, clazz);
360 if (am == NULL) {
361 return NULL;
362 }
363
Steve Block71f2cf12011-10-20 11:56:00 +0100364 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
Elliott Hughes69a017b2011-04-08 14:10:28 -0700366 ScopedUtfChars fileName8(env, fileName);
367 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 return NULL;
369 }
370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000372 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700373 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374
375 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700376 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 return NULL;
378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379
380 //printf("Created Asset Stream: %p\n", a);
381
382 return returnParcelFileDescriptor(env, a, outOffsets);
383}
384
385static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
386 jstring fileName)
387{
388 AssetManager* am = assetManagerForJavaObject(env, clazz);
389 if (am == NULL) {
390 return NULL;
391 }
392
Elliott Hughes69a017b2011-04-08 14:10:28 -0700393 ScopedUtfChars fileName8(env, fileName);
394 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 return NULL;
396 }
397
Elliott Hughes69a017b2011-04-08 14:10:28 -0700398 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399
400 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700401 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 return NULL;
403 }
404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 size_t N = dir->getFileCount();
406
407 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100408 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 delete dir;
411 return NULL;
412 }
413
414 for (size_t i=0; i<N; i++) {
415 const String8& name = dir->getFileName(i);
416 jstring str = env->NewStringUTF(name.string());
417 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 delete dir;
419 return NULL;
420 }
421 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700422 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 }
424
425 delete dir;
426
427 return array;
428}
429
430static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000431 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432{
Ashok Bhat896043d2014-01-17 16:02:38 +0000433 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434
435 //printf("Destroying Asset Stream: %p\n", a);
436
437 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700438 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 return;
440 }
441
442 delete a;
443}
444
445static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000446 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447{
Ashok Bhat896043d2014-01-17 16:02:38 +0000448 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449
450 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700451 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 return -1;
453 }
454
455 uint8_t b;
456 ssize_t res = a->read(&b, 1);
457 return res == 1 ? b : -1;
458}
459
460static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000461 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 jint off, jint len)
463{
Ashok Bhat896043d2014-01-17 16:02:38 +0000464 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465
466 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700467 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 return -1;
469 }
470
471 if (len == 0) {
472 return 0;
473 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 jsize bLen = env->GetArrayLength(bArray);
476 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700477 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 return -1;
479 }
480
481 jbyte* b = env->GetByteArrayElements(bArray, NULL);
482 ssize_t res = a->read(b+off, len);
483 env->ReleaseByteArrayElements(bArray, b, 0);
484
Ashok Bhat896043d2014-01-17 16:02:38 +0000485 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486
487 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700488 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 }
490 return -1;
491}
492
493static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000494 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 jlong offset, jint whence)
496{
Ashok Bhat896043d2014-01-17 16:02:38 +0000497 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498
499 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700500 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 return -1;
502 }
503
504 return a->seek(
505 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
506}
507
508static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000509 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510{
Ashok Bhat896043d2014-01-17 16:02:38 +0000511 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512
513 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700514 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 return -1;
516 }
517
518 return a->getLength();
519}
520
521static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000522 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523{
Ashok Bhat896043d2014-01-17 16:02:38 +0000524 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525
526 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700527 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 return -1;
529 }
530
531 return a->getRemainingLength();
532}
533
534static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
Tao Baia6d7e3f2015-09-01 18:49:54 -0700535 jstring path, jboolean appAsLib)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800536{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700537 ScopedUtfChars path8(env, path);
538 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800539 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 }
541
542 AssetManager* am = assetManagerForJavaObject(env, clazz);
543 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800544 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 }
546
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000547 int32_t cookie;
Tao Baia6d7e3f2015-09-01 18:49:54 -0700548 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000550 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551}
552
Mårten Kongstad48d22322014-01-31 14:43:27 +0100553static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
554 jstring idmapPath)
555{
556 ScopedUtfChars idmapPath8(env, idmapPath);
557 if (idmapPath8.c_str() == NULL) {
558 return 0;
559 }
560
561 AssetManager* am = assetManagerForJavaObject(env, clazz);
562 if (am == NULL) {
563 return 0;
564 }
565
566 int32_t cookie;
567 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
568
569 return (res) ? (jint)cookie : 0;
570}
571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800572static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
573{
574 AssetManager* am = assetManagerForJavaObject(env, clazz);
575 if (am == NULL) {
576 return JNI_TRUE;
577 }
578 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
579}
580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
582{
583 Vector<String8> locales;
584
585 AssetManager* am = assetManagerForJavaObject(env, clazz);
586 if (am == NULL) {
587 return NULL;
588 }
589
590 am->getLocales(&locales);
591
592 const int N = locales.size();
593
594 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
595 if (result == NULL) {
596 return NULL;
597 }
598
599 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700600 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700601 if (str == NULL) {
602 return NULL;
603 }
604 env->SetObjectArrayElement(result, i, str);
605 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 }
607
608 return result;
609}
610
Filip Gruszczynski23493322015-07-29 17:02:59 -0700611static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
612 jobject result = env->NewObject(gConfigurationOffsets.classObject,
613 gConfigurationOffsets.constructor);
614 if (result == NULL) {
615 return NULL;
616 }
617
618 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
619 config.smallestScreenWidthDp);
620 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
621 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
622
623 return result;
624}
625
626static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
627 const Vector<ResTable_config>& configs) {
628 const int N = configs.size();
629 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
630 if (result == NULL) {
631 return NULL;
632 }
633
634 for (int i=0; i<N; i++) {
635 jobject config = constructConfigurationObject(env, configs[i]);
636 if (config == NULL) {
637 env->DeleteLocalRef(result);
638 return NULL;
639 }
640
641 env->SetObjectArrayElement(result, i, config);
642 env->DeleteLocalRef(config);
643 }
644
645 return result;
646}
647
648static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
649 AssetManager* am = assetManagerForJavaObject(env, clazz);
650 if (am == NULL) {
651 return NULL;
652 }
653
654 const ResTable& res(am->getResources());
655 Vector<ResTable_config> configs;
656 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
657
658 return getSizeConfigurationsInternal(env, configs);
659}
660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800661static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
662 jint mcc, jint mnc,
663 jstring locale, jint orientation,
664 jint touchscreen, jint density,
665 jint keyboard, jint keyboardHidden,
666 jint navigation,
667 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700668 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700669 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100670 jint screenLayout, jint uiMode,
671 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672{
673 AssetManager* am = assetManagerForJavaObject(env, clazz);
674 if (am == NULL) {
675 return;
676 }
677
678 ResTable_config config;
679 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700682
Adam Lesinski2738c962015-05-14 14:25:36 -0700683 // Constants duplicated from Java class android.content.res.Configuration.
684 static const jint kScreenLayoutRoundMask = 0x300;
685 static const jint kScreenLayoutRoundShift = 8;
686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 config.mcc = (uint16_t)mcc;
688 config.mnc = (uint16_t)mnc;
689 config.orientation = (uint8_t)orientation;
690 config.touchscreen = (uint8_t)touchscreen;
691 config.density = (uint16_t)density;
692 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700693 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 config.navigation = (uint8_t)navigation;
695 config.screenWidth = (uint16_t)screenWidth;
696 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700697 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700698 config.screenWidthDp = (uint16_t)screenWidthDp;
699 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700700 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100701 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 config.sdkVersion = (uint16_t)sdkVersion;
703 config.minorVersion = 0;
Adam Lesinski2738c962015-05-14 14:25:36 -0700704
705 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
706 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
707 // into screenLayout2.
708 config.screenLayout2 =
709 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
714}
715
716static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
717 jstring name,
718 jstring defType,
719 jstring defPackage)
720{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700721 ScopedStringChars name16(env, name);
722 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 return 0;
724 }
725
726 AssetManager* am = assetManagerForJavaObject(env, clazz);
727 if (am == NULL) {
728 return 0;
729 }
730
Dan Albert66987492014-11-20 11:41:21 -0800731 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
732 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
733 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 jsize defTypeLen = defType
735 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800736 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
737 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
738 NULL))
739 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 jsize defPackageLen = defPackage
741 ? env->GetStringLength(defPackage) : 0;
742
743 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800744 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
745 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746
747 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800748 env->ReleaseStringChars(defPackage,
749 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 }
751 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800752 env->ReleaseStringChars(defType,
753 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755
756 return ident;
757}
758
759static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
760 jint resid)
761{
762 AssetManager* am = assetManagerForJavaObject(env, clazz);
763 if (am == NULL) {
764 return NULL;
765 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700768 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 return NULL;
770 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 String16 str;
773 if (name.package != NULL) {
774 str.setTo(name.package, name.packageLen);
775 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700776 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 if (str.size() > 0) {
778 char16_t div = ':';
779 str.append(&div, 1);
780 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700781 if (name.type8 != NULL) {
782 str.append(String16(name.type8, name.typeLen));
783 } else {
784 str.append(name.type, name.typeLen);
785 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700787 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 if (str.size() > 0) {
789 char16_t div = '/';
790 str.append(&div, 1);
791 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700792 if (name.name8 != NULL) {
793 str.append(String16(name.name8, name.nameLen));
794 } else {
795 str.append(name.name, name.nameLen);
796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800799 return env->NewString((const jchar*)str.string(), str.size());
800}
801
802static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
803 jint resid)
804{
805 AssetManager* am = assetManagerForJavaObject(env, clazz);
806 if (am == NULL) {
807 return NULL;
808 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800810 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700811 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 return NULL;
813 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 if (name.package != NULL) {
816 return env->NewString((const jchar*)name.package, name.packageLen);
817 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 return NULL;
820}
821
822static jstring android_content_AssetManager_getResourceTypeName(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
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700835 if (name.type8 != NULL) {
836 return env->NewStringUTF(name.type8);
837 }
838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 if (name.type != NULL) {
840 return env->NewString((const jchar*)name.type, name.typeLen);
841 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 return NULL;
844}
845
846static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
847 jint resid)
848{
849 AssetManager* am = assetManagerForJavaObject(env, clazz);
850 if (am == NULL) {
851 return NULL;
852 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700855 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 return NULL;
857 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700858
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700859 if (name.name8 != NULL) {
860 return env->NewStringUTF(name.name8);
861 }
862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 if (name.name != NULL) {
864 return env->NewString((const jchar*)name.name, name.nameLen);
865 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 return NULL;
868}
869
870static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
871 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700872 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 jobject outValue,
874 jboolean resolve)
875{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800876 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800877 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700878 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800879 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 AssetManager* am = assetManagerForJavaObject(env, clazz);
881 if (am == NULL) {
882 return 0;
883 }
884 const ResTable& res(am->getResources());
885
886 Res_value value;
887 ResTable_config config;
888 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700889 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800890 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800891 if (block == BAD_INDEX) {
892 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
893 return 0;
894 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800895 }
896 uint32_t ref = ident;
897 if (resolve) {
898 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
899 if (kThrowOnBadId) {
900 if (block == BAD_INDEX) {
901 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
902 return 0;
903 }
904 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000906 if (block >= 0) {
907 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
908 }
909
910 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911}
912
913static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
914 jint ident, jint bagEntryId,
915 jobject outValue, jboolean resolve)
916{
917 AssetManager* am = assetManagerForJavaObject(env, clazz);
918 if (am == NULL) {
919 return 0;
920 }
921 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800923 // Now lock down the resource object and start pulling stuff from it.
924 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 ssize_t block = -1;
927 Res_value value;
928
929 const ResTable::bag_entry* entry = NULL;
930 uint32_t typeSpecFlags;
931 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
932
933 for (ssize_t i=0; i<entryCount; i++) {
934 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
935 block = entry->stringBlock;
936 value = entry->map.value;
937 }
938 entry++;
939 }
940
941 res.unlock();
942
943 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000944 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 uint32_t ref = ident;
948 if (resolve) {
949 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800950 if (kThrowOnBadId) {
951 if (block == BAD_INDEX) {
952 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
953 return 0;
954 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000957 if (block >= 0) {
958 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
959 }
960
961 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962}
963
964static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
965{
966 AssetManager* am = assetManagerForJavaObject(env, clazz);
967 if (am == NULL) {
968 return 0;
969 }
970 return am->getResources().getTableCount();
971}
972
Ashok Bhat896043d2014-01-17 16:02:38 +0000973static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 jint block)
975{
976 AssetManager* am = assetManagerForJavaObject(env, clazz);
977 if (am == NULL) {
978 return 0;
979 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000980 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800981}
982
983static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
984 jint cookie)
985{
986 AssetManager* am = assetManagerForJavaObject(env, clazz);
987 if (am == NULL) {
988 return NULL;
989 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000990 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700992 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 return NULL;
994 }
995 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 return str;
997}
998
Adam Lesinskide898ff2014-01-29 18:20:45 -0800999static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1000{
1001 AssetManager* am = assetManagerForJavaObject(env, clazz);
1002 if (am == NULL) {
1003 return 0;
1004 }
1005
1006 const ResTable& res = am->getResources();
1007
1008 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1009 gSparseArrayOffsets.constructor);
1010 const size_t N = res.getBasePackageCount();
1011 for (size_t i = 0; i < N; i++) {
1012 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -08001013 env->CallVoidMethod(
1014 sparseArray, gSparseArrayOffsets.put,
1015 static_cast<jint>(res.getBasePackageId(i)),
1016 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1017 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -08001018 }
1019 return sparseArray;
1020}
1021
Ashok Bhat896043d2014-01-17 16:02:38 +00001022static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023{
1024 AssetManager* am = assetManagerForJavaObject(env, clazz);
1025 if (am == NULL) {
1026 return 0;
1027 }
Ashok Bhat896043d2014-01-17 16:02:38 +00001028 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029}
1030
1031static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001032 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033{
Ashok Bhat896043d2014-01-17 16:02:38 +00001034 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 delete theme;
1036}
1037
1038static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001039 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 jint styleRes,
1041 jboolean force)
1042{
Ashok Bhat896043d2014-01-17 16:02:38 +00001043 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 theme->applyStyle(styleRes, force ? true : false);
1045}
1046
1047static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001048 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049{
Ashok Bhat896043d2014-01-17 16:02:38 +00001050 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1051 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 dest->setTo(*src);
1053}
1054
Alan Viverettee54d2452015-05-06 10:41:43 -07001055static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1056{
1057 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1058 theme->clear();
1059}
1060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +00001062 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063{
Ashok Bhat896043d2014-01-17 16:02:38 +00001064 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 const ResTable& res(theme->getResTable());
1066
1067 Res_value value;
1068 // XXX value could be different in different configs!
1069 uint32_t typeSpecFlags = 0;
1070 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1071 uint32_t ref = 0;
1072 if (resolve) {
1073 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001074 if (kThrowOnBadId) {
1075 if (block == BAD_INDEX) {
1076 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1077 return 0;
1078 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
1081 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1082}
1083
Alan Viverettec1d52792015-05-05 09:49:03 -07001084static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1085 jlong themeHandle)
1086{
1087 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1088 return theme->getChangingConfigurations();
1089}
1090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001092 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 jstring tag, jstring prefix)
1094{
Ashok Bhat896043d2014-01-17 16:02:38 +00001095 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001097 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 // XXX Need to use params.
1100 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101}
1102
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001103class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1104public:
1105 XmlAttributeFinder(const ResXMLParser* parser)
1106 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1107 , mParser(parser) {}
1108
1109 inline uint32_t getAttribute(jsize index) const {
1110 return mParser->getAttributeNameResID(index);
1111 }
1112
1113private:
1114 const ResXMLParser* mParser;
1115};
1116
1117class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1118public:
1119 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1120 : BackTrackingAttributeFinder(start, end) {}
1121
1122 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1123 return entry->map.name.ident;
1124 }
1125};
1126
Alan Viverette52b999f2014-03-24 18:00:26 -07001127static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1128 jlong themeToken,
1129 jint defStyleAttr,
1130 jint defStyleRes,
1131 jintArray inValues,
1132 jintArray attrs,
1133 jintArray outValues,
1134 jintArray outIndices)
1135{
1136 if (themeToken == 0) {
1137 jniThrowNullPointerException(env, "theme token");
1138 return JNI_FALSE;
1139 }
1140 if (attrs == NULL) {
1141 jniThrowNullPointerException(env, "attrs");
1142 return JNI_FALSE;
1143 }
1144 if (outValues == NULL) {
1145 jniThrowNullPointerException(env, "out values");
1146 return JNI_FALSE;
1147 }
1148
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001149 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001150 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1151 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001152 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001153
1154 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1155 const ResTable& res = theme->getResTable();
1156 ResTable_config config;
1157 Res_value value;
1158
1159 const jsize NI = env->GetArrayLength(attrs);
1160 const jsize NV = env->GetArrayLength(outValues);
1161 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1162 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1163 return JNI_FALSE;
1164 }
1165
1166 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1167 if (src == NULL) {
1168 return JNI_FALSE;
1169 }
1170
1171 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1172 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1173
1174 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1175 jint* dest = baseDest;
1176 if (dest == NULL) {
1177 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1178 return JNI_FALSE;
1179 }
1180
1181 jint* indices = NULL;
1182 int indicesIdx = 0;
1183 if (outIndices != NULL) {
1184 if (env->GetArrayLength(outIndices) > NI) {
1185 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1186 }
1187 }
1188
1189 // Load default style from attribute, if specified...
1190 uint32_t defStyleBagTypeSetFlags = 0;
1191 if (defStyleAttr != 0) {
1192 Res_value value;
1193 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1194 if (value.dataType == Res_value::TYPE_REFERENCE) {
1195 defStyleRes = value.data;
1196 }
1197 }
1198 }
1199
1200 // Now lock down the resource object and start pulling stuff from it.
1201 res.lock();
1202
1203 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001204 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001205 uint32_t defStyleTypeSetFlags = 0;
1206 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001207 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001208 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001209 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1210 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001211
1212 // Now iterate through all of the attributes that the client has requested,
1213 // filling in each with whatever data we can find.
1214 ssize_t block = 0;
1215 uint32_t typeSetFlags;
1216 for (jsize ii=0; ii<NI; ii++) {
1217 const uint32_t curIdent = (uint32_t)src[ii];
1218
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001219 if (kDebugStyles) {
1220 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1221 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001222
1223 // Try to find a value for this attribute... we prioritize values
1224 // coming from, first XML attributes, then XML style, then default
1225 // style, and finally the theme.
1226 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001227 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001228 typeSetFlags = 0;
1229 config.density = 0;
1230
1231 // Retrieve the current input value if available.
1232 if (NSV > 0 && srcValues[ii] != 0) {
1233 block = -1;
1234 value.dataType = Res_value::TYPE_ATTRIBUTE;
1235 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001236 if (kDebugStyles) {
1237 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1238 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001239 }
1240
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001241 if (value.dataType == Res_value::TYPE_NULL) {
1242 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1243 if (defStyleEntry != defStyleEnd) {
1244 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001245 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001246 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001247 if (kDebugStyles) {
1248 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1249 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001250 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001251 }
1252
1253 uint32_t resid = 0;
1254 if (value.dataType != Res_value::TYPE_NULL) {
1255 // Take care of resolving the found resource to its final value.
1256 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1257 &resid, &typeSetFlags, &config);
1258 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001259 if (kDebugStyles) {
1260 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1261 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001262 } else {
1263 // If we still don't have a value for this attribute, try to find
1264 // it in the theme!
1265 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1266 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001267 if (kDebugStyles) {
1268 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1269 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001270 newBlock = res.resolveReference(&value, block, &resid,
1271 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001272 if (kThrowOnBadId) {
1273 if (newBlock == BAD_INDEX) {
1274 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1275 return JNI_FALSE;
1276 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001277 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001278 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001279 if (kDebugStyles) {
1280 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1281 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001282 }
1283 }
1284
1285 // Deal with the special @null value -- it turns back to TYPE_NULL.
1286 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001287 if (kDebugStyles) {
1288 ALOGI("-> Setting to @null!");
1289 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001290 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001291 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001292 block = -1;
1293 }
1294
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001295 if (kDebugStyles) {
1296 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1297 value.data);
1298 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001299
1300 // Write the final value back to Java.
1301 dest[STYLE_TYPE] = value.dataType;
1302 dest[STYLE_DATA] = value.data;
1303 dest[STYLE_ASSET_COOKIE] =
1304 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1305 dest[STYLE_RESOURCE_ID] = resid;
1306 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1307 dest[STYLE_DENSITY] = config.density;
1308
1309 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1310 indicesIdx++;
1311 indices[indicesIdx] = ii;
1312 }
1313
1314 dest += STYLE_NUM_ENTRIES;
1315 }
1316
1317 res.unlock();
1318
1319 if (indices != NULL) {
1320 indices[0] = indicesIdx;
1321 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1322 }
1323 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1324 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1325 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1326
1327 return JNI_TRUE;
1328}
1329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001331 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 jint defStyleAttr,
1333 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001334 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 jintArray attrs,
1336 jintArray outValues,
1337 jintArray outIndices)
1338{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001339 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001340 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001341 return JNI_FALSE;
1342 }
1343 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001344 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001345 return JNI_FALSE;
1346 }
1347 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001348 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 return JNI_FALSE;
1350 }
1351
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001352 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001353 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1354 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1355 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001356 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001357
Ashok Bhat896043d2014-01-17 16:02:38 +00001358 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001359 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001360 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001361 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 Res_value value;
1363
1364 const jsize NI = env->GetArrayLength(attrs);
1365 const jsize NV = env->GetArrayLength(outValues);
1366 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001367 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 return JNI_FALSE;
1369 }
1370
1371 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1372 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 return JNI_FALSE;
1374 }
1375
1376 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1377 jint* dest = baseDest;
1378 if (dest == NULL) {
1379 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 return JNI_FALSE;
1381 }
1382
1383 jint* indices = NULL;
1384 int indicesIdx = 0;
1385 if (outIndices != NULL) {
1386 if (env->GetArrayLength(outIndices) > NI) {
1387 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1388 }
1389 }
1390
1391 // Load default style from attribute, if specified...
1392 uint32_t defStyleBagTypeSetFlags = 0;
1393 if (defStyleAttr != 0) {
1394 Res_value value;
1395 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1396 if (value.dataType == Res_value::TYPE_REFERENCE) {
1397 defStyleRes = value.data;
1398 }
1399 }
1400 }
1401
1402 // Retrieve the style class associated with the current XML tag.
1403 int style = 0;
1404 uint32_t styleBagTypeSetFlags = 0;
1405 if (xmlParser != NULL) {
1406 ssize_t idx = xmlParser->indexOfStyle();
1407 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1408 if (value.dataType == value.TYPE_ATTRIBUTE) {
1409 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1410 value.dataType = Res_value::TYPE_NULL;
1411 }
1412 }
1413 if (value.dataType == value.TYPE_REFERENCE) {
1414 style = value.data;
1415 }
1416 }
1417 }
1418
1419 // Now lock down the resource object and start pulling stuff from it.
1420 res.lock();
1421
1422 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001423 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424 uint32_t defStyleTypeSetFlags = 0;
1425 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001426 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001428 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1429 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430
1431 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001432 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001434 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001436 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1437 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438
1439 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001441 XmlAttributeFinder xmlAttrFinder(xmlParser);
1442 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443
1444 // Now iterate through all of the attributes that the client has requested,
1445 // filling in each with whatever data we can find.
1446 ssize_t block = 0;
1447 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001448 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 const uint32_t curIdent = (uint32_t)src[ii];
1450
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001451 if (kDebugStyles) {
1452 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1453 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 // Try to find a value for this attribute... we prioritize values
1456 // coming from, first XML attributes, then XML style, then default
1457 // style, and finally the theme.
1458 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001459 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001461 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001463 // Walk through the xml attributes looking for the requested attribute.
1464 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1465 if (xmlAttrIdx != xmlAttrEnd) {
1466 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001468 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001469 if (kDebugStyles) {
1470 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1471 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 }
1473
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001474 if (value.dataType == Res_value::TYPE_NULL) {
1475 // Walk through the style class values looking for the requested attribute.
1476 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1477 if (styleAttrEntry != styleAttrEnd) {
1478 // We found the attribute we were looking for.
1479 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001481 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001482 if (kDebugStyles) {
1483 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 }
1487
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001488 if (value.dataType == Res_value::TYPE_NULL) {
1489 // Walk through the default style values looking for the requested attribute.
1490 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1491 if (defStyleAttrEntry != defStyleAttrEnd) {
1492 // We found the attribute we were looking for.
1493 block = defStyleAttrEntry->stringBlock;
1494 typeSetFlags = styleTypeSetFlags;
1495 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001496 if (kDebugStyles) {
1497 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 }
1501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 uint32_t resid = 0;
1503 if (value.dataType != Res_value::TYPE_NULL) {
1504 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001505 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1506 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001507 if (newBlock >= 0) {
1508 block = newBlock;
1509 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001510
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001511 if (kDebugStyles) {
1512 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 } else {
1515 // If we still don't have a value for this attribute, try to find
1516 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1518 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001519 if (kDebugStyles) {
1520 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1521 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001522 newBlock = res.resolveReference(&value, block, &resid,
1523 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001524 if (kThrowOnBadId) {
1525 if (newBlock == BAD_INDEX) {
1526 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1527 return JNI_FALSE;
1528 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001529 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001530
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001531 if (newBlock >= 0) {
1532 block = newBlock;
1533 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001534
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001535 if (kDebugStyles) {
1536 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1537 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 }
1539 }
1540
1541 // Deal with the special @null value -- it turns back to TYPE_NULL.
1542 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001543 if (kDebugStyles) {
1544 ALOGI("-> Setting to @null!");
1545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001547 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001548 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
1550
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001551 if (kDebugStyles) {
1552 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554
1555 // Write the final value back to Java.
1556 dest[STYLE_TYPE] = value.dataType;
1557 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001558 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1559 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 dest[STYLE_RESOURCE_ID] = resid;
1561 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001562 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1565 indicesIdx++;
1566 indices[indicesIdx] = ii;
1567 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 dest += STYLE_NUM_ENTRIES;
1570 }
1571
1572 res.unlock();
1573
1574 if (indices != NULL) {
1575 indices[0] = indicesIdx;
1576 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1577 }
1578 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1579 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1580
1581 return JNI_TRUE;
1582}
1583
1584static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001585 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 jintArray attrs,
1587 jintArray outValues,
1588 jintArray outIndices)
1589{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001590 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001591 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001592 return JNI_FALSE;
1593 }
1594 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001595 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001596 return JNI_FALSE;
1597 }
1598 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001599 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 return JNI_FALSE;
1601 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 AssetManager* am = assetManagerForJavaObject(env, clazz);
1604 if (am == NULL) {
1605 return JNI_FALSE;
1606 }
1607 const ResTable& res(am->getResources());
1608 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001609 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 const jsize NI = env->GetArrayLength(attrs);
1613 const jsize NV = env->GetArrayLength(outValues);
1614 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001615 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 return JNI_FALSE;
1617 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1620 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 return JNI_FALSE;
1622 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1625 jint* dest = baseDest;
1626 if (dest == NULL) {
1627 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 return JNI_FALSE;
1629 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 jint* indices = NULL;
1632 int indicesIdx = 0;
1633 if (outIndices != NULL) {
1634 if (env->GetArrayLength(outIndices) > NI) {
1635 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1636 }
1637 }
1638
1639 // Now lock down the resource object and start pulling stuff from it.
1640 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 // Retrieve the XML attributes, if requested.
1643 const jsize NX = xmlParser->getAttributeCount();
1644 jsize ix=0;
1645 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 // Now iterate through all of the attributes that the client has requested,
1650 // filling in each with whatever data we can find.
1651 ssize_t block = 0;
1652 uint32_t typeSetFlags;
1653 for (jsize ii=0; ii<NI; ii++) {
1654 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 // Try to find a value for this attribute...
1657 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001658 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001660 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001663 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 ix++;
1665 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1666 }
1667 // Retrieve the current XML attribute if it matches, and step to next.
1668 if (ix < NX && curIdent == curXmlAttr) {
1669 block = kXmlBlock;
1670 xmlParser->getAttributeValue(ix, &value);
1671 ix++;
1672 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1673 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1676 uint32_t resid = 0;
1677 if (value.dataType != Res_value::TYPE_NULL) {
1678 // Take care of resolving the found resource to its final value.
1679 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001680 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1681 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001682 if (kThrowOnBadId) {
1683 if (newBlock == BAD_INDEX) {
1684 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1685 return JNI_FALSE;
1686 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 if (newBlock >= 0) block = newBlock;
1689 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 // Deal with the special @null value -- it turns back to TYPE_NULL.
1692 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1693 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001694 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 // Write the final value back to Java.
1700 dest[STYLE_TYPE] = value.dataType;
1701 dest[STYLE_DATA] = value.data;
1702 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001703 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 dest[STYLE_RESOURCE_ID] = resid;
1705 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001706 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1709 indicesIdx++;
1710 indices[indicesIdx] = ii;
1711 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 dest += STYLE_NUM_ENTRIES;
1714 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 if (indices != NULL) {
1719 indices[0] = indicesIdx;
1720 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1721 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001723 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1724 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 return JNI_TRUE;
1727}
1728
1729static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1730 jint id)
1731{
1732 AssetManager* am = assetManagerForJavaObject(env, clazz);
1733 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001734 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 }
1736 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 res.lock();
1739 const ResTable::bag_entry* defStyleEnt = NULL;
1740 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1741 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001742
Ashok Bhat896043d2014-01-17 16:02:38 +00001743 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744}
1745
1746static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1747 jint id,
1748 jintArray outValues)
1749{
1750 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001751 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752 return JNI_FALSE;
1753 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 AssetManager* am = assetManagerForJavaObject(env, clazz);
1756 if (am == NULL) {
1757 return JNI_FALSE;
1758 }
1759 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001760 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001761 Res_value value;
1762 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1767 jint* dest = baseDest;
1768 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001769 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 return JNI_FALSE;
1771 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 // Now lock down the resource object and start pulling stuff from it.
1774 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 const ResTable::bag_entry* arrayEnt = NULL;
1777 uint32_t arrayTypeSetFlags = 0;
1778 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1779 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1780 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 int i = 0;
1783 uint32_t typeSetFlags;
1784 while (i < NV && arrayEnt < endArrayEnt) {
1785 block = arrayEnt->stringBlock;
1786 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001787 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 uint32_t resid = 0;
1791 if (value.dataType != Res_value::TYPE_NULL) {
1792 // Take care of resolving the found resource to its final value.
1793 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001794 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1795 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001796 if (kThrowOnBadId) {
1797 if (newBlock == BAD_INDEX) {
1798 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1799 return JNI_FALSE;
1800 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 if (newBlock >= 0) block = newBlock;
1803 }
1804
1805 // Deal with the special @null value -- it turns back to TYPE_NULL.
1806 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1807 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001808 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001809 }
1810
1811 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1812
1813 // Write the final value back to Java.
1814 dest[STYLE_TYPE] = value.dataType;
1815 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001816 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001817 dest[STYLE_RESOURCE_ID] = resid;
1818 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001819 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 dest += STYLE_NUM_ENTRIES;
1821 i+= STYLE_NUM_ENTRIES;
1822 arrayEnt++;
1823 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001829 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001831 return i;
1832}
1833
Ashok Bhat896043d2014-01-17 16:02:38 +00001834static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 jint cookie,
1836 jstring fileName)
1837{
1838 AssetManager* am = assetManagerForJavaObject(env, clazz);
1839 if (am == NULL) {
1840 return 0;
1841 }
1842
Steve Block71f2cf12011-10-20 11:56:00 +01001843 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844
Elliott Hughes69a017b2011-04-08 14:10:28 -07001845 ScopedUtfChars fileName8(env, fileName);
1846 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 return 0;
1848 }
1849
Adam Lesinskide898ff2014-01-29 18:20:45 -08001850 int32_t assetCookie = static_cast<int32_t>(cookie);
1851 Asset* a = assetCookie
1852 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1853 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001854
1855 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001856 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 return 0;
1858 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859
Adam Lesinskide898ff2014-01-29 18:20:45 -08001860 const DynamicRefTable* dynamicRefTable =
1861 am->getResources().getDynamicRefTableForCookie(assetCookie);
1862 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1864 a->close();
1865 delete a;
1866
1867 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001868 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 return 0;
1870 }
1871
Ashok Bhat896043d2014-01-17 16:02:38 +00001872 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873}
1874
1875static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1876 jint arrayResId)
1877{
1878 AssetManager* am = assetManagerForJavaObject(env, clazz);
1879 if (am == NULL) {
1880 return NULL;
1881 }
1882 const ResTable& res(am->getResources());
1883
1884 const ResTable::bag_entry* startOfBag;
1885 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1886 if (N < 0) {
1887 return NULL;
1888 }
1889
1890 jintArray array = env->NewIntArray(N * 2);
1891 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 res.unlockBag(startOfBag);
1893 return NULL;
1894 }
1895
1896 Res_value value;
1897 const ResTable::bag_entry* bag = startOfBag;
1898 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1899 jint stringIndex = -1;
1900 jint stringBlock = 0;
1901 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001903 // Take care of resolving the found resource to its final value.
1904 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1905 if (value.dataType == Res_value::TYPE_STRING) {
1906 stringIndex = value.data;
1907 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001908
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001909 if (kThrowOnBadId) {
1910 if (stringBlock == BAD_INDEX) {
1911 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1912 return array;
1913 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001914 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 //todo: It might be faster to allocate a C array to contain
1917 // the blocknums and indices, put them in there and then
1918 // do just one SetIntArrayRegion()
1919 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1920 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1921 j = j + 2;
1922 }
1923 res.unlockBag(startOfBag);
1924 return array;
1925}
1926
1927static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1928 jint arrayResId)
1929{
1930 AssetManager* am = assetManagerForJavaObject(env, clazz);
1931 if (am == NULL) {
1932 return NULL;
1933 }
1934 const ResTable& res(am->getResources());
1935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 const ResTable::bag_entry* startOfBag;
1937 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1938 if (N < 0) {
1939 return NULL;
1940 }
1941
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001942 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001943 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 res.unlockBag(startOfBag);
1945 return NULL;
1946 }
1947
1948 Res_value value;
1949 const ResTable::bag_entry* bag = startOfBag;
1950 size_t strLen = 0;
1951 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1952 value = bag->map.value;
1953 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 // Take care of resolving the found resource to its final value.
1956 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001957 if (kThrowOnBadId) {
1958 if (block == BAD_INDEX) {
1959 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1960 return array;
1961 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001962 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001964 const ResStringPool* pool = res.getTableStringBlock(block);
1965 const char* str8 = pool->string8At(value.data, &strLen);
1966 if (str8 != NULL) {
1967 str = env->NewStringUTF(str8);
1968 } else {
1969 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001970 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1971 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001972 }
1973
1974 // If one of our NewString{UTF} calls failed due to memory, an
1975 // exception will be pending.
1976 if (env->ExceptionCheck()) {
1977 res.unlockBag(startOfBag);
1978 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 }
Kenny Root780d2a12010-02-22 22:36:26 -08001980
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001981 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001982
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001983 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1984 // If we have a large amount of strings in our array, we might
1985 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001986 env->DeleteLocalRef(str);
1987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 }
1989 res.unlockBag(startOfBag);
1990 return array;
1991}
1992
1993static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1994 jint arrayResId)
1995{
1996 AssetManager* am = assetManagerForJavaObject(env, clazz);
1997 if (am == NULL) {
1998 return NULL;
1999 }
2000 const ResTable& res(am->getResources());
2001
2002 const ResTable::bag_entry* startOfBag;
2003 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
2004 if (N < 0) {
2005 return NULL;
2006 }
2007
2008 jintArray array = env->NewIntArray(N);
2009 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 res.unlockBag(startOfBag);
2011 return NULL;
2012 }
2013
2014 Res_value value;
2015 const ResTable::bag_entry* bag = startOfBag;
2016 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2017 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07002018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 // Take care of resolving the found resource to its final value.
2020 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08002021 if (kThrowOnBadId) {
2022 if (block == BAD_INDEX) {
2023 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
2024 return array;
2025 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08002026 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 if (value.dataType >= Res_value::TYPE_FIRST_INT
2028 && value.dataType <= Res_value::TYPE_LAST_INT) {
2029 int intVal = value.data;
2030 env->SetIntArrayRegion(array, i, 1, &intVal);
2031 }
2032 }
2033 res.unlockBag(startOfBag);
2034 return array;
2035}
2036
Jon Miranda042ad632014-09-03 17:57:35 -07002037static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
2038 jint styleId)
2039{
2040 AssetManager* am = assetManagerForJavaObject(env, clazz);
2041 if (am == NULL) {
2042 return NULL;
2043 }
2044 const ResTable& res(am->getResources());
2045
2046 const ResTable::bag_entry* startOfBag;
2047 const ssize_t N = res.lockBag(styleId, &startOfBag);
2048 if (N < 0) {
2049 return NULL;
2050 }
2051
2052 jintArray array = env->NewIntArray(N);
2053 if (array == NULL) {
2054 res.unlockBag(startOfBag);
2055 return NULL;
2056 }
2057
Jon Miranda042ad632014-09-03 17:57:35 -07002058 const ResTable::bag_entry* bag = startOfBag;
2059 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
2060 int resourceId = bag->map.name.ident;
2061 env->SetIntArrayRegion(array, i, 1, &resourceId);
2062 }
2063 res.unlockBag(startOfBag);
2064 return array;
2065}
2066
Mårten Kongstad48d22322014-01-31 14:43:27 +01002067static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068{
Mårten Kongstad48d22322014-01-31 14:43:27 +01002069 if (isSystem) {
2070 verifySystemIdmaps();
2071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 AssetManager* am = new AssetManager();
2073 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07002074 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 return;
2076 }
2077
2078 am->addDefaultAssets();
2079
Steve Block71f2cf12011-10-20 11:56:00 +01002080 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00002081 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082}
2083
2084static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
2085{
2086 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00002087 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01002088 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 if (am != NULL) {
2090 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002091 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002092 }
2093}
2094
2095static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2096{
2097 return Asset::getGlobalCount();
2098}
2099
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002100static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2101{
2102 String8 alloc = Asset::getAssetAllocations();
2103 if (alloc.length() <= 0) {
2104 return NULL;
2105 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002106
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002107 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002108 return str;
2109}
2110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002111static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2112{
2113 return AssetManager::getGlobalCount();
2114}
2115
2116// ----------------------------------------------------------------------------
2117
2118/*
2119 * JNI registration.
2120 */
Daniel Micay76f6a862015-09-19 17:31:01 -04002121static const JNINativeMethod gAssetManagerMethods[] = {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 /* name, signature, funcPtr */
2123
2124 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002125 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 (void*) android_content_AssetManager_openAsset },
2127 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2128 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002129 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 (void*) android_content_AssetManager_openNonAssetNative },
2131 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2132 (void*) android_content_AssetManager_openNonAssetFdNative },
2133 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2134 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002135 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002137 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002139 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002140 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002141 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 (void*) android_content_AssetManager_seekAsset },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002143 { "getAssetLength", "!(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144 (void*) android_content_AssetManager_getAssetLength },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002145 { "getAssetRemainingLength", "!(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 (void*) android_content_AssetManager_getAssetRemainingLength },
Tao Baia6d7e3f2015-09-01 18:49:54 -07002147 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad30113132014-11-07 10:52:17 +01002149 { "addOverlayPathNative", "(Ljava/lang/String;)I",
Mårten Kongstad48d22322014-01-31 14:43:27 +01002150 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 { "isUpToDate", "()Z",
2152 (void*) android_content_AssetManager_isUpToDate },
2153
2154 // Resources.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 { "getLocales", "()[Ljava/lang/String;",
2156 (void*) android_content_AssetManager_getLocales },
Filip Gruszczynski23493322015-07-29 17:02:59 -07002157 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
2158 (void*) android_content_AssetManager_getSizeConfigurations },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002159 { "setConfiguration", "!(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 (void*) android_content_AssetManager_setConfiguration },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002161 { "getResourceIdentifier","!(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 (void*) android_content_AssetManager_getResourceIdentifier },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002163 { "getResourceName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164 (void*) android_content_AssetManager_getResourceName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002165 { "getResourcePackageName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 (void*) android_content_AssetManager_getResourcePackageName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002167 { "getResourceTypeName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168 (void*) android_content_AssetManager_getResourceTypeName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002169 { "getResourceEntryName","!(I)Ljava/lang/String;",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170 (void*) android_content_AssetManager_getResourceEntryName },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002171 { "loadResourceValue","!(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 (void*) android_content_AssetManager_loadResourceValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002173 { "loadResourceBagValue","!(IILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 (void*) android_content_AssetManager_loadResourceBagValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002175 { "getStringBlockCount","!()I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 (void*) android_content_AssetManager_getStringBlockCount },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002177 { "getNativeStringBlock","!(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 (void*) android_content_AssetManager_getNativeStringBlock },
2179 { "getCookieName","(I)Ljava/lang/String;",
2180 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002181 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2182 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183
2184 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002185 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002187 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002189 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002191 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 (void*) android_content_AssetManager_copyTheme },
Alan Viverettee54d2452015-05-06 10:41:43 -07002193 { "clearTheme", "(J)V",
2194 (void*) android_content_AssetManager_clearTheme },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002195 { "loadThemeAttributeValue", "!(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 (void*) android_content_AssetManager_loadThemeAttributeValue },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002197 { "getThemeChangingConfigurations", "!(J)I",
Alan Viverettec1d52792015-05-05 09:49:03 -07002198 (void*) android_content_AssetManager_getThemeChangingConfigurations },
Ashok Bhat896043d2014-01-17 16:02:38 +00002199 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 (void*) android_content_AssetManager_dumpTheme },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002201 { "applyStyle","!(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 (void*) android_content_AssetManager_applyStyle },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002203 { "resolveAttrs","!(JII[I[I[I[I)Z",
Alan Viverette607bd842014-09-12 12:36:35 -07002204 (void*) android_content_AssetManager_resolveAttrs },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002205 { "retrieveAttributes","!(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 (void*) android_content_AssetManager_retrieveAttributes },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002207 { "getArraySize","!(I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 (void*) android_content_AssetManager_getArraySize },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002209 { "retrieveArray","!(I[I)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 (void*) android_content_AssetManager_retrieveArray },
2211
2212 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002213 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002214 (void*) android_content_AssetManager_openXmlAssetNative },
2215
2216 // Arrays.
2217 { "getArrayStringResource","(I)[Ljava/lang/String;",
2218 (void*) android_content_AssetManager_getArrayStringResource },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002219 { "getArrayStringInfo","!(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002220 (void*) android_content_AssetManager_getArrayStringInfo },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002221 { "getArrayIntResource","!(I)[I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 (void*) android_content_AssetManager_getArrayIntResource },
Jeff Sharkey46cfd932015-11-02 18:39:45 -08002223 { "getStyleAttributes","!(I)[I",
Jon Miranda042ad632014-09-03 17:57:35 -07002224 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002225
2226 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002227 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002228 (void*) android_content_AssetManager_init },
2229 { "destroy", "()V",
2230 (void*) android_content_AssetManager_destroy },
2231 { "getGlobalAssetCount", "()I",
2232 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002233 { "getAssetAllocations", "()Ljava/lang/String;",
2234 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002235 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002236 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002237};
2238
2239int register_android_content_AssetManager(JNIEnv* env)
2240{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002241 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2242 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2243 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2244 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2245 "Ljava/lang/CharSequence;");
2246 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2247 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2248 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2249 "changingConfigurations", "I");
2250 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251
Andreas Gampe987f79f2014-11-18 17:29:46 -08002252 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2253 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2254 "Landroid/os/ParcelFileDescriptor;");
2255 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2256 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257
Andreas Gampe987f79f2014-11-18 17:29:46 -08002258 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2259 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002260
Andreas Gampe987f79f2014-11-18 17:29:46 -08002261 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2262 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263
Andreas Gampe987f79f2014-11-18 17:29:46 -08002264 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2265 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2266 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2267 "<init>", "()V");
2268 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2269 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002270
Filip Gruszczynski23493322015-07-29 17:02:59 -07002271 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
2272 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
2273 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
2274 "<init>", "()V");
2275 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2276 "smallestScreenWidthDp", "I");
2277 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
2278 "screenWidthDp", "I");
2279 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
2280 "screenHeightDp", "I");
2281
Andreas Gampe987f79f2014-11-18 17:29:46 -08002282 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2283 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284}
2285
2286}; // namespace android