blob: 94098c91880c07b7e2efdc10d311c01cdda8605f [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
Dianne Hackbornb8d81672009-11-20 14:26:42 -080020#define DEBUG_STYLES(x) //x
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080021#define THROW_ON_BAD_ID 0
Dianne Hackbornb8d81672009-11-20 14:26:42 -080022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023#include <android_runtime/android_util_AssetManager.h>
24
25#include "jni.h"
26#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070027#include "ScopedStringChars.h"
28#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include "android_util_Binder.h"
30#include <utils/misc.h>
31#include <android_runtime/AndroidRuntime.h>
32#include <utils/Log.h>
33
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080034#include <androidfw/Asset.h>
35#include <androidfw/AssetManager.h>
36#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Mårten Kongstad48d22322014-01-31 14:43:27 +010038#include <private/android_filesystem_config.h> // for AID_SYSTEM
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010041#include <sys/types.h>
42#include <sys/wait.h>
43
44#include <linux/capability.h>
45extern "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
51// ----------------------------------------------------------------------------
52
53static struct typedvalue_offsets_t
54{
55 jfieldID mType;
56 jfieldID mData;
57 jfieldID mString;
58 jfieldID mAssetCookie;
59 jfieldID mResourceId;
60 jfieldID mChangingConfigurations;
61 jfieldID mDensity;
62} gTypedValueOffsets;
63
64static struct assetfiledescriptor_offsets_t
65{
66 jfieldID mFd;
67 jfieldID mStartOffset;
68 jfieldID mLength;
69} gAssetFileDescriptorOffsets;
70
71static struct assetmanager_offsets_t
72{
73 jfieldID mObject;
74} gAssetManagerOffsets;
75
Adam Lesinskide898ff2014-01-29 18:20:45 -080076static struct sparsearray_offsets_t
77{
78 jclass classObject;
79 jmethodID constructor;
80 jmethodID put;
81} gSparseArrayOffsets;
82
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083jclass g_stringClass = NULL;
84
85// ----------------------------------------------------------------------------
86
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070088 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 STYLE_TYPE = 0,
90 STYLE_DATA = 1,
91 STYLE_ASSET_COOKIE = 2,
92 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070093 STYLE_CHANGING_CONFIGURATIONS = 4,
94 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095};
96
97static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
98 const Res_value& value, uint32_t ref, ssize_t block,
99 uint32_t typeSpecFlags, ResTable_config* config = NULL);
100
101jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
102 const Res_value& value, uint32_t ref, ssize_t block,
103 uint32_t typeSpecFlags, ResTable_config* config)
104{
105 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
106 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000107 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
109 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
110 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
111 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
112 typeSpecFlags);
113 if (config != NULL) {
114 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
115 }
116 return block;
117}
118
Mårten Kongstad48d22322014-01-31 14:43:27 +0100119// This is called by zygote (running as user root) as part of preloadResources.
120static void verifySystemIdmaps()
121{
122 pid_t pid;
123 char system_id[10];
124
125 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
126
127 switch (pid = fork()) {
128 case -1:
129 ALOGE("failed to fork for idmap: %s", strerror(errno));
130 break;
131 case 0: // child
132 {
133 struct __user_cap_header_struct capheader;
134 struct __user_cap_data_struct capdata;
135
136 memset(&capheader, 0, sizeof(capheader));
137 memset(&capdata, 0, sizeof(capdata));
138
139 capheader.version = _LINUX_CAPABILITY_VERSION;
140 capheader.pid = 0;
141
142 if (capget(&capheader, &capdata) != 0) {
143 ALOGE("capget: %s\n", strerror(errno));
144 exit(1);
145 }
146
147 capdata.effective = capdata.permitted;
148 if (capset(&capheader, &capdata) != 0) {
149 ALOGE("capset: %s\n", strerror(errno));
150 exit(1);
151 }
152
153 if (setgid(AID_SYSTEM) != 0) {
154 ALOGE("setgid: %s\n", strerror(errno));
155 exit(1);
156 }
157
158 if (setuid(AID_SYSTEM) != 0) {
159 ALOGE("setuid: %s\n", strerror(errno));
160 exit(1);
161 }
162
163 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
164 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
165 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
166 ALOGE("failed to execl for idmap: %s", strerror(errno));
167 exit(1); // should never get here
168 }
169 break;
170 default: // parent
171 waitpid(pid, NULL, 0);
172 break;
173 }
174}
175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176// ----------------------------------------------------------------------------
177
178// this guy is exported to other jni routines
179AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
180{
Ashok Bhat896043d2014-01-17 16:02:38 +0000181 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
182 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 if (am != NULL) {
184 return am;
185 }
186 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
187 return NULL;
188}
189
Ashok Bhat896043d2014-01-17 16:02:38 +0000190static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 jstring fileName, jint mode)
192{
193 AssetManager* am = assetManagerForJavaObject(env, clazz);
194 if (am == NULL) {
195 return 0;
196 }
197
Steve Block71f2cf12011-10-20 11:56:00 +0100198 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
Elliott Hughes69a017b2011-04-08 14:10:28 -0700200 ScopedUtfChars fileName8(env, fileName);
201 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000202 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 return -1;
204 }
205
206 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
207 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700208 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 return -1;
210 }
211
Elliott Hughes69a017b2011-04-08 14:10:28 -0700212 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213
214 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700215 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 return -1;
217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
219 //printf("Created Asset Stream: %p\n", a);
220
Ashok Bhat896043d2014-01-17 16:02:38 +0000221 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222}
223
224static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
225{
Kenny Rootddb76c42010-11-24 12:56:06 -0800226 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 int fd = a->openFileDescriptor(&startOffset, &length);
228 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700231 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 "This file can not be opened as a file descriptor; it is probably compressed");
233 return NULL;
234 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
237 if (offsets == NULL) {
238 close(fd);
239 return NULL;
240 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 offsets[0] = startOffset;
243 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700246
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700247 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 if (fileDesc == NULL) {
249 close(fd);
250 return NULL;
251 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 return newParcelFileDescriptor(env, fileDesc);
254}
255
256static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
257 jstring fileName, jlongArray outOffsets)
258{
259 AssetManager* am = assetManagerForJavaObject(env, clazz);
260 if (am == NULL) {
261 return NULL;
262 }
263
Steve Block71f2cf12011-10-20 11:56:00 +0100264 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
Elliott Hughes69a017b2011-04-08 14:10:28 -0700266 ScopedUtfChars fileName8(env, fileName);
267 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 return NULL;
269 }
270
Elliott Hughes69a017b2011-04-08 14:10:28 -0700271 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
273 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700274 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 return NULL;
276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277
278 //printf("Created Asset Stream: %p\n", a);
279
280 return returnParcelFileDescriptor(env, a, outOffsets);
281}
282
Ashok Bhat896043d2014-01-17 16:02:38 +0000283static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 jint cookie,
285 jstring fileName,
286 jint mode)
287{
288 AssetManager* am = assetManagerForJavaObject(env, clazz);
289 if (am == NULL) {
290 return 0;
291 }
292
Steve Block71f2cf12011-10-20 11:56:00 +0100293 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
Elliott Hughes69a017b2011-04-08 14:10:28 -0700295 ScopedUtfChars fileName8(env, fileName);
296 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 return -1;
298 }
299
300 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
301 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700302 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 return -1;
304 }
305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000307 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
308 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700309 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700312 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 return -1;
314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 //printf("Created Asset Stream: %p\n", a);
317
Ashok Bhat896043d2014-01-17 16:02:38 +0000318 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319}
320
321static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
322 jint cookie,
323 jstring fileName,
324 jlongArray outOffsets)
325{
326 AssetManager* am = assetManagerForJavaObject(env, clazz);
327 if (am == NULL) {
328 return NULL;
329 }
330
Steve Block71f2cf12011-10-20 11:56:00 +0100331 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332
Elliott Hughes69a017b2011-04-08 14:10:28 -0700333 ScopedUtfChars fileName8(env, fileName);
334 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 return NULL;
336 }
337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000339 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700340 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341
342 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700343 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 return NULL;
345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346
347 //printf("Created Asset Stream: %p\n", a);
348
349 return returnParcelFileDescriptor(env, a, outOffsets);
350}
351
352static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
353 jstring fileName)
354{
355 AssetManager* am = assetManagerForJavaObject(env, clazz);
356 if (am == NULL) {
357 return NULL;
358 }
359
Elliott Hughes69a017b2011-04-08 14:10:28 -0700360 ScopedUtfChars fileName8(env, fileName);
361 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 return NULL;
363 }
364
Elliott Hughes69a017b2011-04-08 14:10:28 -0700365 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366
367 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700368 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 return NULL;
370 }
371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 size_t N = dir->getFileCount();
373
374 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100375 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 delete dir;
378 return NULL;
379 }
380
381 for (size_t i=0; i<N; i++) {
382 const String8& name = dir->getFileName(i);
383 jstring str = env->NewStringUTF(name.string());
384 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 delete dir;
386 return NULL;
387 }
388 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700389 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 }
391
392 delete dir;
393
394 return array;
395}
396
397static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000398 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399{
Ashok Bhat896043d2014-01-17 16:02:38 +0000400 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401
402 //printf("Destroying Asset Stream: %p\n", a);
403
404 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700405 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 return;
407 }
408
409 delete a;
410}
411
412static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000413 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414{
Ashok Bhat896043d2014-01-17 16:02:38 +0000415 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416
417 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700418 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 return -1;
420 }
421
422 uint8_t b;
423 ssize_t res = a->read(&b, 1);
424 return res == 1 ? b : -1;
425}
426
427static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000428 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 jint off, jint len)
430{
Ashok Bhat896043d2014-01-17 16:02:38 +0000431 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432
433 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700434 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 return -1;
436 }
437
438 if (len == 0) {
439 return 0;
440 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 jsize bLen = env->GetArrayLength(bArray);
443 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700444 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 return -1;
446 }
447
448 jbyte* b = env->GetByteArrayElements(bArray, NULL);
449 ssize_t res = a->read(b+off, len);
450 env->ReleaseByteArrayElements(bArray, b, 0);
451
Ashok Bhat896043d2014-01-17 16:02:38 +0000452 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453
454 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700455 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 }
457 return -1;
458}
459
460static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000461 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 jlong offset, jint whence)
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) {
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 return a->seek(
472 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
473}
474
475static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000476 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477{
Ashok Bhat896043d2014-01-17 16:02:38 +0000478 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479
480 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700481 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 return -1;
483 }
484
485 return a->getLength();
486}
487
488static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000489 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490{
Ashok Bhat896043d2014-01-17 16:02:38 +0000491 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492
493 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700494 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 return -1;
496 }
497
498 return a->getRemainingLength();
499}
500
501static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
502 jstring path)
503{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700504 ScopedUtfChars path8(env, path);
505 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800506 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 }
508
509 AssetManager* am = assetManagerForJavaObject(env, clazz);
510 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800511 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 }
513
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000514 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700515 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000517 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518}
519
Mårten Kongstad48d22322014-01-31 14:43:27 +0100520static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
521 jstring idmapPath)
522{
523 ScopedUtfChars idmapPath8(env, idmapPath);
524 if (idmapPath8.c_str() == NULL) {
525 return 0;
526 }
527
528 AssetManager* am = assetManagerForJavaObject(env, clazz);
529 if (am == NULL) {
530 return 0;
531 }
532
533 int32_t cookie;
534 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
535
536 return (res) ? (jint)cookie : 0;
537}
538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
540{
541 AssetManager* am = assetManagerForJavaObject(env, clazz);
542 if (am == NULL) {
543 return JNI_TRUE;
544 }
545 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
546}
547
548static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
549 jstring locale)
550{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700551 ScopedUtfChars locale8(env, locale);
552 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 return;
554 }
555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 AssetManager* am = assetManagerForJavaObject(env, clazz);
557 if (am == NULL) {
558 return;
559 }
560
Elliott Hughes69a017b2011-04-08 14:10:28 -0700561 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562}
563
564static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
565{
566 Vector<String8> locales;
567
568 AssetManager* am = assetManagerForJavaObject(env, clazz);
569 if (am == NULL) {
570 return NULL;
571 }
572
573 am->getLocales(&locales);
574
575 const int N = locales.size();
576
577 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
578 if (result == NULL) {
579 return NULL;
580 }
581
582 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700583 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700584 if (str == NULL) {
585 return NULL;
586 }
587 env->SetObjectArrayElement(result, i, str);
588 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 }
590
591 return result;
592}
593
594static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
595 jint mcc, jint mnc,
596 jstring locale, jint orientation,
597 jint touchscreen, jint density,
598 jint keyboard, jint keyboardHidden,
599 jint navigation,
600 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700601 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700602 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100603 jint screenLayout, jint uiMode,
604 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605{
606 AssetManager* am = assetManagerForJavaObject(env, clazz);
607 if (am == NULL) {
608 return;
609 }
610
611 ResTable_config config;
612 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 config.mcc = (uint16_t)mcc;
617 config.mnc = (uint16_t)mnc;
618 config.orientation = (uint8_t)orientation;
619 config.touchscreen = (uint8_t)touchscreen;
620 config.density = (uint16_t)density;
621 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700622 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 config.navigation = (uint8_t)navigation;
624 config.screenWidth = (uint16_t)screenWidth;
625 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700626 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700627 config.screenWidthDp = (uint16_t)screenWidthDp;
628 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700629 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100630 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 config.sdkVersion = (uint16_t)sdkVersion;
632 config.minorVersion = 0;
633 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
636}
637
638static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
639 jstring name,
640 jstring defType,
641 jstring defPackage)
642{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700643 ScopedStringChars name16(env, name);
644 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 return 0;
646 }
647
648 AssetManager* am = assetManagerForJavaObject(env, clazz);
649 if (am == NULL) {
650 return 0;
651 }
652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 const char16_t* defType16 = defType
654 ? env->GetStringChars(defType, NULL) : NULL;
655 jsize defTypeLen = defType
656 ? env->GetStringLength(defType) : 0;
657 const char16_t* defPackage16 = defPackage
658 ? env->GetStringChars(defPackage, NULL) : NULL;
659 jsize defPackageLen = defPackage
660 ? env->GetStringLength(defPackage) : 0;
661
662 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700663 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
665 if (defPackage16) {
666 env->ReleaseStringChars(defPackage, defPackage16);
667 }
668 if (defType16) {
669 env->ReleaseStringChars(defType, defType16);
670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 return ident;
673}
674
675static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
676 jint resid)
677{
678 AssetManager* am = assetManagerForJavaObject(env, clazz);
679 if (am == NULL) {
680 return NULL;
681 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700684 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 return NULL;
686 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 String16 str;
689 if (name.package != NULL) {
690 str.setTo(name.package, name.packageLen);
691 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700692 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 if (str.size() > 0) {
694 char16_t div = ':';
695 str.append(&div, 1);
696 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700697 if (name.type8 != NULL) {
698 str.append(String16(name.type8, name.typeLen));
699 } else {
700 str.append(name.type, name.typeLen);
701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700703 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 if (str.size() > 0) {
705 char16_t div = '/';
706 str.append(&div, 1);
707 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700708 if (name.name8 != NULL) {
709 str.append(String16(name.name8, name.nameLen));
710 } else {
711 str.append(name.name, name.nameLen);
712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 return env->NewString((const jchar*)str.string(), str.size());
716}
717
718static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
719 jint resid)
720{
721 AssetManager* am = assetManagerForJavaObject(env, clazz);
722 if (am == NULL) {
723 return NULL;
724 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700727 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 return NULL;
729 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (name.package != NULL) {
732 return env->NewString((const jchar*)name.package, name.packageLen);
733 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 return NULL;
736}
737
738static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
739 jint resid)
740{
741 AssetManager* am = assetManagerForJavaObject(env, clazz);
742 if (am == NULL) {
743 return NULL;
744 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700747 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 return NULL;
749 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700750
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700751 if (name.type8 != NULL) {
752 return env->NewStringUTF(name.type8);
753 }
754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 if (name.type != NULL) {
756 return env->NewString((const jchar*)name.type, name.typeLen);
757 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 return NULL;
760}
761
762static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
763 jint resid)
764{
765 AssetManager* am = assetManagerForJavaObject(env, clazz);
766 if (am == NULL) {
767 return NULL;
768 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700771 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 return NULL;
773 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700774
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700775 if (name.name8 != NULL) {
776 return env->NewStringUTF(name.name8);
777 }
778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 if (name.name != NULL) {
780 return env->NewString((const jchar*)name.name, name.nameLen);
781 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 return NULL;
784}
785
786static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
787 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700788 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 jobject outValue,
790 jboolean resolve)
791{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800792 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800793 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700794 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 AssetManager* am = assetManagerForJavaObject(env, clazz);
797 if (am == NULL) {
798 return 0;
799 }
800 const ResTable& res(am->getResources());
801
802 Res_value value;
803 ResTable_config config;
804 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700805 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800806#if THROW_ON_BAD_ID
807 if (block == BAD_INDEX) {
808 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
809 return 0;
810 }
811#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 uint32_t ref = ident;
813 if (resolve) {
Dianne Hackbornfb5c3db2012-05-18 15:24:24 -0700814 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800815#if THROW_ON_BAD_ID
816 if (block == BAD_INDEX) {
817 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
818 return 0;
819 }
820#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000822 if (block >= 0) {
823 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
824 }
825
826 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827}
828
829static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
830 jint ident, jint bagEntryId,
831 jobject outValue, jboolean resolve)
832{
833 AssetManager* am = assetManagerForJavaObject(env, clazz);
834 if (am == NULL) {
835 return 0;
836 }
837 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 // Now lock down the resource object and start pulling stuff from it.
840 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 ssize_t block = -1;
843 Res_value value;
844
845 const ResTable::bag_entry* entry = NULL;
846 uint32_t typeSpecFlags;
847 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
848
849 for (ssize_t i=0; i<entryCount; i++) {
850 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
851 block = entry->stringBlock;
852 value = entry->map.value;
853 }
854 entry++;
855 }
856
857 res.unlock();
858
859 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000860 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 uint32_t ref = ident;
864 if (resolve) {
865 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800866#if THROW_ON_BAD_ID
867 if (block == BAD_INDEX) {
868 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
869 return 0;
870 }
871#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000873 if (block >= 0) {
874 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
875 }
876
877 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878}
879
880static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
881{
882 AssetManager* am = assetManagerForJavaObject(env, clazz);
883 if (am == NULL) {
884 return 0;
885 }
886 return am->getResources().getTableCount();
887}
888
Ashok Bhat896043d2014-01-17 16:02:38 +0000889static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 jint block)
891{
892 AssetManager* am = assetManagerForJavaObject(env, clazz);
893 if (am == NULL) {
894 return 0;
895 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000896 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897}
898
899static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
900 jint cookie)
901{
902 AssetManager* am = assetManagerForJavaObject(env, clazz);
903 if (am == NULL) {
904 return NULL;
905 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000906 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700908 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 return NULL;
910 }
911 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 return str;
913}
914
Adam Lesinskide898ff2014-01-29 18:20:45 -0800915static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
916{
917 AssetManager* am = assetManagerForJavaObject(env, clazz);
918 if (am == NULL) {
919 return 0;
920 }
921
922 const ResTable& res = am->getResources();
923
924 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
925 gSparseArrayOffsets.constructor);
926 const size_t N = res.getBasePackageCount();
927 for (size_t i = 0; i < N; i++) {
928 const String16 name = res.getBasePackageName(i);
929 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
930 env->NewString(name, name.size()));
931 }
932 return sparseArray;
933}
934
Ashok Bhat896043d2014-01-17 16:02:38 +0000935static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936{
937 AssetManager* am = assetManagerForJavaObject(env, clazz);
938 if (am == NULL) {
939 return 0;
940 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000941 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942}
943
944static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000945 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946{
Ashok Bhat896043d2014-01-17 16:02:38 +0000947 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 delete theme;
949}
950
951static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000952 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 jint styleRes,
954 jboolean force)
955{
Ashok Bhat896043d2014-01-17 16:02:38 +0000956 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 theme->applyStyle(styleRes, force ? true : false);
958}
959
960static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000961 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962{
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
964 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 dest->setTo(*src);
966}
967
968static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000969 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970{
Ashok Bhat896043d2014-01-17 16:02:38 +0000971 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 const ResTable& res(theme->getResTable());
973
974 Res_value value;
975 // XXX value could be different in different configs!
976 uint32_t typeSpecFlags = 0;
977 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
978 uint32_t ref = 0;
979 if (resolve) {
980 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800981#if THROW_ON_BAD_ID
982 if (block == BAD_INDEX) {
983 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
984 return 0;
985 }
986#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 }
988 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
989}
990
991static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000992 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 jstring tag, jstring prefix)
994{
Ashok Bhat896043d2014-01-17 16:02:38 +0000995 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 const ResTable& res(theme->getResTable());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 // XXX Need to use params.
999 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000}
1001
Alan Viverette52b999f2014-03-24 18:00:26 -07001002static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1003 jlong themeToken,
1004 jint defStyleAttr,
1005 jint defStyleRes,
1006 jintArray inValues,
1007 jintArray attrs,
1008 jintArray outValues,
1009 jintArray outIndices)
1010{
1011 if (themeToken == 0) {
1012 jniThrowNullPointerException(env, "theme token");
1013 return JNI_FALSE;
1014 }
1015 if (attrs == NULL) {
1016 jniThrowNullPointerException(env, "attrs");
1017 return JNI_FALSE;
1018 }
1019 if (outValues == NULL) {
1020 jniThrowNullPointerException(env, "out values");
1021 return JNI_FALSE;
1022 }
1023
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001024 DEBUG_STYLES(ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001025 themeToken, defStyleAttr, defStyleRes));
1026
1027 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1028 const ResTable& res = theme->getResTable();
1029 ResTable_config config;
1030 Res_value value;
1031
1032 const jsize NI = env->GetArrayLength(attrs);
1033 const jsize NV = env->GetArrayLength(outValues);
1034 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1035 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1036 return JNI_FALSE;
1037 }
1038
1039 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1040 if (src == NULL) {
1041 return JNI_FALSE;
1042 }
1043
1044 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1045 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1046
1047 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1048 jint* dest = baseDest;
1049 if (dest == NULL) {
1050 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1051 return JNI_FALSE;
1052 }
1053
1054 jint* indices = NULL;
1055 int indicesIdx = 0;
1056 if (outIndices != NULL) {
1057 if (env->GetArrayLength(outIndices) > NI) {
1058 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1059 }
1060 }
1061
1062 // Load default style from attribute, if specified...
1063 uint32_t defStyleBagTypeSetFlags = 0;
1064 if (defStyleAttr != 0) {
1065 Res_value value;
1066 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1067 if (value.dataType == Res_value::TYPE_REFERENCE) {
1068 defStyleRes = value.data;
1069 }
1070 }
1071 }
1072
1073 // Now lock down the resource object and start pulling stuff from it.
1074 res.lock();
1075
1076 // Retrieve the default style bag, if requested.
1077 const ResTable::bag_entry* defStyleEnt = NULL;
1078 uint32_t defStyleTypeSetFlags = 0;
1079 ssize_t bagOff = defStyleRes != 0
1080 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1081 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1082 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1083 (bagOff >= 0 ? bagOff : 0);;
1084
1085 // Now iterate through all of the attributes that the client has requested,
1086 // filling in each with whatever data we can find.
1087 ssize_t block = 0;
1088 uint32_t typeSetFlags;
1089 for (jsize ii=0; ii<NI; ii++) {
1090 const uint32_t curIdent = (uint32_t)src[ii];
1091
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001092 DEBUG_STYLES(ALOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Alan Viverette52b999f2014-03-24 18:00:26 -07001093
1094 // Try to find a value for this attribute... we prioritize values
1095 // coming from, first XML attributes, then XML style, then default
1096 // style, and finally the theme.
1097 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001098 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001099 typeSetFlags = 0;
1100 config.density = 0;
1101
1102 // Retrieve the current input value if available.
1103 if (NSV > 0 && srcValues[ii] != 0) {
1104 block = -1;
1105 value.dataType = Res_value::TYPE_ATTRIBUTE;
1106 value.data = srcValues[ii];
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001107 DEBUG_STYLES(ALOGI("-> From values: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001108 value.dataType, value.data));
1109 }
1110
1111 // Skip through the default style values until the end or the next possible match.
1112 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1113 defStyleEnt++;
1114 }
1115 // Retrieve the current default style attribute if it matches, and step to next.
1116 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1117 if (value.dataType == Res_value::TYPE_NULL) {
1118 block = defStyleEnt->stringBlock;
1119 typeSetFlags = defStyleTypeSetFlags;
1120 value = defStyleEnt->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001121 DEBUG_STYLES(ALOGI("-> From def style: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001122 value.dataType, value.data));
1123 }
1124 defStyleEnt++;
1125 }
1126
1127 uint32_t resid = 0;
1128 if (value.dataType != Res_value::TYPE_NULL) {
1129 // Take care of resolving the found resource to its final value.
1130 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1131 &resid, &typeSetFlags, &config);
1132 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001133 DEBUG_STYLES(ALOGI("-> Resolved attr: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001134 value.dataType, value.data));
1135 } else {
1136 // If we still don't have a value for this attribute, try to find
1137 // it in the theme!
1138 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1139 if (newBlock >= 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001140 DEBUG_STYLES(ALOGI("-> From theme: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001141 value.dataType, value.data));
1142 newBlock = res.resolveReference(&value, block, &resid,
1143 &typeSetFlags, &config);
1144#if THROW_ON_BAD_ID
1145 if (newBlock == BAD_INDEX) {
1146 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1147 return JNI_FALSE;
1148 }
1149#endif
1150 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001151 DEBUG_STYLES(ALOGI("-> Resolved theme: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001152 value.dataType, value.data));
1153 }
1154 }
1155
1156 // Deal with the special @null value -- it turns back to TYPE_NULL.
1157 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001158 DEBUG_STYLES(ALOGI("-> Setting to @null!"));
Alan Viverette52b999f2014-03-24 18:00:26 -07001159 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001160 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001161 block = -1;
1162 }
1163
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001164 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001165 curIdent, value.dataType, value.data));
1166
1167 // Write the final value back to Java.
1168 dest[STYLE_TYPE] = value.dataType;
1169 dest[STYLE_DATA] = value.data;
1170 dest[STYLE_ASSET_COOKIE] =
1171 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1172 dest[STYLE_RESOURCE_ID] = resid;
1173 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1174 dest[STYLE_DENSITY] = config.density;
1175
1176 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1177 indicesIdx++;
1178 indices[indicesIdx] = ii;
1179 }
1180
1181 dest += STYLE_NUM_ENTRIES;
1182 }
1183
1184 res.unlock();
1185
1186 if (indices != NULL) {
1187 indices[0] = indicesIdx;
1188 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1189 }
1190 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1191 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1192 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1193
1194 return JNI_TRUE;
1195}
1196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001198 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 jint defStyleAttr,
1200 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001201 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 jintArray attrs,
1203 jintArray outValues,
1204 jintArray outIndices)
1205{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001206 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001207 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001208 return JNI_FALSE;
1209 }
1210 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001211 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001212 return JNI_FALSE;
1213 }
1214 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001215 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 return JNI_FALSE;
1217 }
1218
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001219 DEBUG_STYLES(ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001220 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001221
Ashok Bhat896043d2014-01-17 16:02:38 +00001222 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001224 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001225 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 Res_value value;
1227
1228 const jsize NI = env->GetArrayLength(attrs);
1229 const jsize NV = env->GetArrayLength(outValues);
1230 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001231 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 return JNI_FALSE;
1233 }
1234
1235 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1236 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 return JNI_FALSE;
1238 }
1239
1240 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1241 jint* dest = baseDest;
1242 if (dest == NULL) {
1243 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 return JNI_FALSE;
1245 }
1246
1247 jint* indices = NULL;
1248 int indicesIdx = 0;
1249 if (outIndices != NULL) {
1250 if (env->GetArrayLength(outIndices) > NI) {
1251 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1252 }
1253 }
1254
1255 // Load default style from attribute, if specified...
1256 uint32_t defStyleBagTypeSetFlags = 0;
1257 if (defStyleAttr != 0) {
1258 Res_value value;
1259 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1260 if (value.dataType == Res_value::TYPE_REFERENCE) {
1261 defStyleRes = value.data;
1262 }
1263 }
1264 }
1265
1266 // Retrieve the style class associated with the current XML tag.
1267 int style = 0;
1268 uint32_t styleBagTypeSetFlags = 0;
1269 if (xmlParser != NULL) {
1270 ssize_t idx = xmlParser->indexOfStyle();
1271 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1272 if (value.dataType == value.TYPE_ATTRIBUTE) {
1273 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1274 value.dataType = Res_value::TYPE_NULL;
1275 }
1276 }
1277 if (value.dataType == value.TYPE_REFERENCE) {
1278 style = value.data;
1279 }
1280 }
1281 }
1282
1283 // Now lock down the resource object and start pulling stuff from it.
1284 res.lock();
1285
1286 // Retrieve the default style bag, if requested.
1287 const ResTable::bag_entry* defStyleEnt = NULL;
1288 uint32_t defStyleTypeSetFlags = 0;
1289 ssize_t bagOff = defStyleRes != 0
1290 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1291 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1292 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1293 (bagOff >= 0 ? bagOff : 0);
1294
1295 // Retrieve the style class bag, if requested.
1296 const ResTable::bag_entry* styleEnt = NULL;
1297 uint32_t styleTypeSetFlags = 0;
1298 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1299 styleTypeSetFlags |= styleBagTypeSetFlags;
1300 const ResTable::bag_entry* endStyleEnt = styleEnt +
1301 (bagOff >= 0 ? bagOff : 0);
1302
1303 // Retrieve the XML attributes, if requested.
1304 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1305 jsize ix=0;
1306 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1307
1308 static const ssize_t kXmlBlock = 0x10000000;
1309
1310 // Now iterate through all of the attributes that the client has requested,
1311 // filling in each with whatever data we can find.
1312 ssize_t block = 0;
1313 uint32_t typeSetFlags;
1314 for (jsize ii=0; ii<NI; ii++) {
1315 const uint32_t curIdent = (uint32_t)src[ii];
1316
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001317 DEBUG_STYLES(ALOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 // Try to find a value for this attribute... we prioritize values
1320 // coming from, first XML attributes, then XML style, then default
1321 // style, and finally the theme.
1322 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001323 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001325 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326
1327 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001328 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 ix++;
1330 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1331 }
1332 // Retrieve the current XML attribute if it matches, and step to next.
1333 if (ix < NX && curIdent == curXmlAttr) {
1334 block = kXmlBlock;
1335 xmlParser->getAttributeValue(ix, &value);
1336 ix++;
1337 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001338 DEBUG_STYLES(ALOGI("-> From XML: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001339 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 }
1341
1342 // Skip through the style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001343 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 styleEnt++;
1345 }
1346 // Retrieve the current style attribute if it matches, and step to next.
1347 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1348 if (value.dataType == Res_value::TYPE_NULL) {
1349 block = styleEnt->stringBlock;
1350 typeSetFlags = styleTypeSetFlags;
1351 value = styleEnt->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001352 DEBUG_STYLES(ALOGI("-> From style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001353 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354 }
1355 styleEnt++;
1356 }
1357
1358 // Skip through the default style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001359 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 defStyleEnt++;
1361 }
1362 // Retrieve the current default style attribute if it matches, and step to next.
1363 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1364 if (value.dataType == Res_value::TYPE_NULL) {
1365 block = defStyleEnt->stringBlock;
1366 typeSetFlags = defStyleTypeSetFlags;
1367 value = defStyleEnt->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001368 DEBUG_STYLES(ALOGI("-> From def style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001369 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 }
1371 defStyleEnt++;
1372 }
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 uint32_t resid = 0;
1375 if (value.dataType != Res_value::TYPE_NULL) {
1376 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001377 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1378 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001380 DEBUG_STYLES(ALOGI("-> Resolved attr: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001381 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001382 } else {
1383 // If we still don't have a value for this attribute, try to find
1384 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1386 if (newBlock >= 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001387 DEBUG_STYLES(ALOGI("-> From theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001388 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001389 newBlock = res.resolveReference(&value, block, &resid,
1390 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001391#if THROW_ON_BAD_ID
1392 if (newBlock == BAD_INDEX) {
1393 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1394 return JNI_FALSE;
1395 }
1396#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001398 DEBUG_STYLES(ALOGI("-> Resolved theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001399 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 }
1401 }
1402
1403 // Deal with the special @null value -- it turns back to TYPE_NULL.
1404 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001405 DEBUG_STYLES(ALOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001407 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001408 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 }
1410
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001411 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001412 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413
1414 // Write the final value back to Java.
1415 dest[STYLE_TYPE] = value.dataType;
1416 dest[STYLE_DATA] = value.data;
1417 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001418 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 dest[STYLE_RESOURCE_ID] = resid;
1420 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001421 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1424 indicesIdx++;
1425 indices[indicesIdx] = ii;
1426 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 dest += STYLE_NUM_ENTRIES;
1429 }
1430
1431 res.unlock();
1432
1433 if (indices != NULL) {
1434 indices[0] = indicesIdx;
1435 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1436 }
1437 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1438 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1439
1440 return JNI_TRUE;
1441}
1442
1443static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001444 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 jintArray attrs,
1446 jintArray outValues,
1447 jintArray outIndices)
1448{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001449 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001450 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001451 return JNI_FALSE;
1452 }
1453 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001454 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001455 return JNI_FALSE;
1456 }
1457 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001458 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 return JNI_FALSE;
1460 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 AssetManager* am = assetManagerForJavaObject(env, clazz);
1463 if (am == NULL) {
1464 return JNI_FALSE;
1465 }
1466 const ResTable& res(am->getResources());
1467 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001468 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 const jsize NI = env->GetArrayLength(attrs);
1472 const jsize NV = env->GetArrayLength(outValues);
1473 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001474 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 return JNI_FALSE;
1476 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1479 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 return JNI_FALSE;
1481 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1484 jint* dest = baseDest;
1485 if (dest == NULL) {
1486 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 return JNI_FALSE;
1488 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 jint* indices = NULL;
1491 int indicesIdx = 0;
1492 if (outIndices != NULL) {
1493 if (env->GetArrayLength(outIndices) > NI) {
1494 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1495 }
1496 }
1497
1498 // Now lock down the resource object and start pulling stuff from it.
1499 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 // Retrieve the XML attributes, if requested.
1502 const jsize NX = xmlParser->getAttributeCount();
1503 jsize ix=0;
1504 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 // Now iterate through all of the attributes that the client has requested,
1509 // filling in each with whatever data we can find.
1510 ssize_t block = 0;
1511 uint32_t typeSetFlags;
1512 for (jsize ii=0; ii<NI; ii++) {
1513 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 // Try to find a value for this attribute...
1516 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001517 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001518 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001519 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001522 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 ix++;
1524 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1525 }
1526 // Retrieve the current XML attribute if it matches, and step to next.
1527 if (ix < NX && curIdent == curXmlAttr) {
1528 block = kXmlBlock;
1529 xmlParser->getAttributeValue(ix, &value);
1530 ix++;
1531 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1532 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1535 uint32_t resid = 0;
1536 if (value.dataType != Res_value::TYPE_NULL) {
1537 // Take care of resolving the found resource to its final value.
1538 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001539 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1540 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001541#if THROW_ON_BAD_ID
1542 if (newBlock == BAD_INDEX) {
1543 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1544 return JNI_FALSE;
1545 }
1546#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (newBlock >= 0) block = newBlock;
1548 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 // Deal with the special @null value -- it turns back to TYPE_NULL.
1551 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1552 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001553 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 // Write the final value back to Java.
1559 dest[STYLE_TYPE] = value.dataType;
1560 dest[STYLE_DATA] = value.data;
1561 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001562 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 dest[STYLE_RESOURCE_ID] = resid;
1564 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001565 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1568 indicesIdx++;
1569 indices[indicesIdx] = ii;
1570 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 dest += STYLE_NUM_ENTRIES;
1573 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 if (indices != NULL) {
1578 indices[0] = indicesIdx;
1579 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1580 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1583 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 return JNI_TRUE;
1586}
1587
1588static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1589 jint id)
1590{
1591 AssetManager* am = assetManagerForJavaObject(env, clazz);
1592 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001593 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 }
1595 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 res.lock();
1598 const ResTable::bag_entry* defStyleEnt = NULL;
1599 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1600 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601
Ashok Bhat896043d2014-01-17 16:02:38 +00001602 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603}
1604
1605static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1606 jint id,
1607 jintArray outValues)
1608{
1609 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001610 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 return JNI_FALSE;
1612 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 AssetManager* am = assetManagerForJavaObject(env, clazz);
1615 if (am == NULL) {
1616 return JNI_FALSE;
1617 }
1618 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001619 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 Res_value value;
1621 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1626 jint* dest = baseDest;
1627 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001628 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 return JNI_FALSE;
1630 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 // Now lock down the resource object and start pulling stuff from it.
1633 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 const ResTable::bag_entry* arrayEnt = NULL;
1636 uint32_t arrayTypeSetFlags = 0;
1637 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1638 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1639 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 int i = 0;
1642 uint32_t typeSetFlags;
1643 while (i < NV && arrayEnt < endArrayEnt) {
1644 block = arrayEnt->stringBlock;
1645 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001646 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 uint32_t resid = 0;
1650 if (value.dataType != Res_value::TYPE_NULL) {
1651 // Take care of resolving the found resource to its final value.
1652 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001653 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1654 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001655#if THROW_ON_BAD_ID
1656 if (newBlock == BAD_INDEX) {
1657 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1658 return JNI_FALSE;
1659 }
1660#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 if (newBlock >= 0) block = newBlock;
1662 }
1663
1664 // Deal with the special @null value -- it turns back to TYPE_NULL.
1665 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1666 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001667 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 }
1669
1670 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1671
1672 // Write the final value back to Java.
1673 dest[STYLE_TYPE] = value.dataType;
1674 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001675 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 dest[STYLE_RESOURCE_ID] = resid;
1677 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001678 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 dest += STYLE_NUM_ENTRIES;
1680 i+= STYLE_NUM_ENTRIES;
1681 arrayEnt++;
1682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 return i;
1691}
1692
Ashok Bhat896043d2014-01-17 16:02:38 +00001693static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694 jint cookie,
1695 jstring fileName)
1696{
1697 AssetManager* am = assetManagerForJavaObject(env, clazz);
1698 if (am == NULL) {
1699 return 0;
1700 }
1701
Steve Block71f2cf12011-10-20 11:56:00 +01001702 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001703
Elliott Hughes69a017b2011-04-08 14:10:28 -07001704 ScopedUtfChars fileName8(env, fileName);
1705 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 return 0;
1707 }
1708
Adam Lesinskide898ff2014-01-29 18:20:45 -08001709 int32_t assetCookie = static_cast<int32_t>(cookie);
1710 Asset* a = assetCookie
1711 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1712 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713
1714 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001715 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 return 0;
1717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718
Adam Lesinskide898ff2014-01-29 18:20:45 -08001719 const DynamicRefTable* dynamicRefTable =
1720 am->getResources().getDynamicRefTableForCookie(assetCookie);
1721 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001722 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1723 a->close();
1724 delete a;
1725
1726 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001727 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 return 0;
1729 }
1730
Ashok Bhat896043d2014-01-17 16:02:38 +00001731 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001732}
1733
1734static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1735 jint arrayResId)
1736{
1737 AssetManager* am = assetManagerForJavaObject(env, clazz);
1738 if (am == NULL) {
1739 return NULL;
1740 }
1741 const ResTable& res(am->getResources());
1742
1743 const ResTable::bag_entry* startOfBag;
1744 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1745 if (N < 0) {
1746 return NULL;
1747 }
1748
1749 jintArray array = env->NewIntArray(N * 2);
1750 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 res.unlockBag(startOfBag);
1752 return NULL;
1753 }
1754
1755 Res_value value;
1756 const ResTable::bag_entry* bag = startOfBag;
1757 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1758 jint stringIndex = -1;
1759 jint stringBlock = 0;
1760 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 // Take care of resolving the found resource to its final value.
1763 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1764 if (value.dataType == Res_value::TYPE_STRING) {
1765 stringIndex = value.data;
1766 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001767
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001768#if THROW_ON_BAD_ID
1769 if (stringBlock == BAD_INDEX) {
1770 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1771 return array;
1772 }
1773#endif
Elliott Hughes69a017b2011-04-08 14:10:28 -07001774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 //todo: It might be faster to allocate a C array to contain
1776 // the blocknums and indices, put them in there and then
1777 // do just one SetIntArrayRegion()
1778 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1779 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1780 j = j + 2;
1781 }
1782 res.unlockBag(startOfBag);
1783 return array;
1784}
1785
1786static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1787 jint arrayResId)
1788{
1789 AssetManager* am = assetManagerForJavaObject(env, clazz);
1790 if (am == NULL) {
1791 return NULL;
1792 }
1793 const ResTable& res(am->getResources());
1794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 const ResTable::bag_entry* startOfBag;
1796 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1797 if (N < 0) {
1798 return NULL;
1799 }
1800
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001801 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001802 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 res.unlockBag(startOfBag);
1804 return NULL;
1805 }
1806
1807 Res_value value;
1808 const ResTable::bag_entry* bag = startOfBag;
1809 size_t strLen = 0;
1810 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1811 value = bag->map.value;
1812 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 // Take care of resolving the found resource to its final value.
1815 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001816#if THROW_ON_BAD_ID
1817 if (block == BAD_INDEX) {
1818 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1819 return array;
1820 }
1821#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001823 const ResStringPool* pool = res.getTableStringBlock(block);
1824 const char* str8 = pool->string8At(value.data, &strLen);
1825 if (str8 != NULL) {
1826 str = env->NewStringUTF(str8);
1827 } else {
1828 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1829 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001830 }
1831
1832 // If one of our NewString{UTF} calls failed due to memory, an
1833 // exception will be pending.
1834 if (env->ExceptionCheck()) {
1835 res.unlockBag(startOfBag);
1836 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 }
Kenny Root780d2a12010-02-22 22:36:26 -08001838
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001839 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001840
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001841 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1842 // If we have a large amount of strings in our array, we might
1843 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001844 env->DeleteLocalRef(str);
1845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 }
1847 res.unlockBag(startOfBag);
1848 return array;
1849}
1850
1851static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1852 jint arrayResId)
1853{
1854 AssetManager* am = assetManagerForJavaObject(env, clazz);
1855 if (am == NULL) {
1856 return NULL;
1857 }
1858 const ResTable& res(am->getResources());
1859
1860 const ResTable::bag_entry* startOfBag;
1861 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1862 if (N < 0) {
1863 return NULL;
1864 }
1865
1866 jintArray array = env->NewIntArray(N);
1867 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 res.unlockBag(startOfBag);
1869 return NULL;
1870 }
1871
1872 Res_value value;
1873 const ResTable::bag_entry* bag = startOfBag;
1874 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1875 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001877 // Take care of resolving the found resource to its final value.
1878 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001879#if THROW_ON_BAD_ID
1880 if (block == BAD_INDEX) {
1881 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1882 return array;
1883 }
1884#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 if (value.dataType >= Res_value::TYPE_FIRST_INT
1886 && value.dataType <= Res_value::TYPE_LAST_INT) {
1887 int intVal = value.data;
1888 env->SetIntArrayRegion(array, i, 1, &intVal);
1889 }
1890 }
1891 res.unlockBag(startOfBag);
1892 return array;
1893}
1894
Jon Miranda042ad632014-09-03 17:57:35 -07001895static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1896 jint styleId)
1897{
1898 AssetManager* am = assetManagerForJavaObject(env, clazz);
1899 if (am == NULL) {
1900 return NULL;
1901 }
1902 const ResTable& res(am->getResources());
1903
1904 const ResTable::bag_entry* startOfBag;
1905 const ssize_t N = res.lockBag(styleId, &startOfBag);
1906 if (N < 0) {
1907 return NULL;
1908 }
1909
1910 jintArray array = env->NewIntArray(N);
1911 if (array == NULL) {
1912 res.unlockBag(startOfBag);
1913 return NULL;
1914 }
1915
1916 Res_value value;
1917 const ResTable::bag_entry* bag = startOfBag;
1918 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1919 int resourceId = bag->map.name.ident;
1920 env->SetIntArrayRegion(array, i, 1, &resourceId);
1921 }
1922 res.unlockBag(startOfBag);
1923 return array;
1924}
1925
Mårten Kongstad48d22322014-01-31 14:43:27 +01001926static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001928 if (isSystem) {
1929 verifySystemIdmaps();
1930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 AssetManager* am = new AssetManager();
1932 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001933 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 return;
1935 }
1936
1937 am->addDefaultAssets();
1938
Steve Block71f2cf12011-10-20 11:56:00 +01001939 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001940 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941}
1942
1943static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1944{
1945 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001946 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001947 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 if (am != NULL) {
1949 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001950 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951 }
1952}
1953
1954static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1955{
1956 return Asset::getGlobalCount();
1957}
1958
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001959static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1960{
1961 String8 alloc = Asset::getAssetAllocations();
1962 if (alloc.length() <= 0) {
1963 return NULL;
1964 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001965
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001966 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001967 return str;
1968}
1969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1971{
1972 return AssetManager::getGlobalCount();
1973}
1974
1975// ----------------------------------------------------------------------------
1976
1977/*
1978 * JNI registration.
1979 */
1980static JNINativeMethod gAssetManagerMethods[] = {
1981 /* name, signature, funcPtr */
1982
1983 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00001984 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 (void*) android_content_AssetManager_openAsset },
1986 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1987 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00001988 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 (void*) android_content_AssetManager_openNonAssetNative },
1990 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1991 (void*) android_content_AssetManager_openNonAssetFdNative },
1992 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1993 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00001994 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001996 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00001998 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002000 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002002 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002004 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002005 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002006 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002008 { "addOverlayPath", "(Ljava/lang/String;)I",
2009 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 { "isUpToDate", "()Z",
2011 (void*) android_content_AssetManager_isUpToDate },
2012
2013 // Resources.
2014 { "setLocale", "(Ljava/lang/String;)V",
2015 (void*) android_content_AssetManager_setLocale },
2016 { "getLocales", "()[Ljava/lang/String;",
2017 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002018 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 (void*) android_content_AssetManager_setConfiguration },
2020 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2021 (void*) android_content_AssetManager_getResourceIdentifier },
2022 { "getResourceName","(I)Ljava/lang/String;",
2023 (void*) android_content_AssetManager_getResourceName },
2024 { "getResourcePackageName","(I)Ljava/lang/String;",
2025 (void*) android_content_AssetManager_getResourcePackageName },
2026 { "getResourceTypeName","(I)Ljava/lang/String;",
2027 (void*) android_content_AssetManager_getResourceTypeName },
2028 { "getResourceEntryName","(I)Ljava/lang/String;",
2029 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002030 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 (void*) android_content_AssetManager_loadResourceValue },
2032 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2033 (void*) android_content_AssetManager_loadResourceBagValue },
2034 { "getStringBlockCount","()I",
2035 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002036 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 (void*) android_content_AssetManager_getNativeStringBlock },
2038 { "getCookieName","(I)Ljava/lang/String;",
2039 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002040 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2041 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042
2043 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002044 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002046 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002048 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002050 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002052 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002054 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002056 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002058 { "resolveAttrs","(JII[I[I[I[I)Z",
2059 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002060 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 (void*) android_content_AssetManager_retrieveAttributes },
2062 { "getArraySize","(I)I",
2063 (void*) android_content_AssetManager_getArraySize },
2064 { "retrieveArray","(I[I)I",
2065 (void*) android_content_AssetManager_retrieveArray },
2066
2067 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002068 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 (void*) android_content_AssetManager_openXmlAssetNative },
2070
2071 // Arrays.
2072 { "getArrayStringResource","(I)[Ljava/lang/String;",
2073 (void*) android_content_AssetManager_getArrayStringResource },
2074 { "getArrayStringInfo","(I)[I",
2075 (void*) android_content_AssetManager_getArrayStringInfo },
2076 { "getArrayIntResource","(I)[I",
2077 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002078 { "getStyleAttributes","(I)[I",
2079 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080
2081 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002082 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_init },
2084 { "destroy", "()V",
2085 (void*) android_content_AssetManager_destroy },
2086 { "getGlobalAssetCount", "()I",
2087 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002088 { "getAssetAllocations", "()Ljava/lang/String;",
2089 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 { "getGlobalAssetManagerCount", "()I",
2091 (void*) android_content_AssetManager_getGlobalAssetCount },
2092};
2093
2094int register_android_content_AssetManager(JNIEnv* env)
2095{
2096 jclass typedValue = env->FindClass("android/util/TypedValue");
2097 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
2098 gTypedValueOffsets.mType
2099 = env->GetFieldID(typedValue, "type", "I");
2100 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
2101 gTypedValueOffsets.mData
2102 = env->GetFieldID(typedValue, "data", "I");
2103 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
2104 gTypedValueOffsets.mString
2105 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
2106 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
2107 gTypedValueOffsets.mAssetCookie
2108 = env->GetFieldID(typedValue, "assetCookie", "I");
2109 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
2110 gTypedValueOffsets.mResourceId
2111 = env->GetFieldID(typedValue, "resourceId", "I");
2112 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
2113 gTypedValueOffsets.mChangingConfigurations
2114 = env->GetFieldID(typedValue, "changingConfigurations", "I");
2115 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
2116 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
2117 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
2118
2119 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
2120 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
2121 gAssetFileDescriptorOffsets.mFd
2122 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
2123 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
2124 gAssetFileDescriptorOffsets.mStartOffset
2125 = env->GetFieldID(assetFd, "mStartOffset", "J");
2126 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
2127 gAssetFileDescriptorOffsets.mLength
2128 = env->GetFieldID(assetFd, "mLength", "J");
2129 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
2130
2131 jclass assetManager = env->FindClass("android/content/res/AssetManager");
2132 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
2133 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00002134 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
2136
Carl Shapiroc1318ba2011-03-03 14:22:28 -08002137 jclass stringClass = env->FindClass("java/lang/String");
2138 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
2139 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01002140 LOG_FATAL_IF(g_stringClass == NULL, "Unable to create global reference for class java/lang/String");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002141
Adam Lesinskide898ff2014-01-29 18:20:45 -08002142 jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
2143 LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
2144 gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
2145 gSparseArrayOffsets.constructor =
2146 env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
2147 LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
2148 gSparseArrayOffsets.put =
2149 env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
2150 LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
2151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 return AndroidRuntime::registerNativeMethods(env,
2153 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
2154}
2155
2156}; // namespace android