blob: 396f3ec7a1761ceb0183b4fd1fbb1dd55d68cf5c [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;
1098 value.data = 0;
1099 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;
1160 block = -1;
1161 }
1162
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001163 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001164 curIdent, value.dataType, value.data));
1165
1166 // Write the final value back to Java.
1167 dest[STYLE_TYPE] = value.dataType;
1168 dest[STYLE_DATA] = value.data;
1169 dest[STYLE_ASSET_COOKIE] =
1170 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1171 dest[STYLE_RESOURCE_ID] = resid;
1172 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1173 dest[STYLE_DENSITY] = config.density;
1174
1175 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1176 indicesIdx++;
1177 indices[indicesIdx] = ii;
1178 }
1179
1180 dest += STYLE_NUM_ENTRIES;
1181 }
1182
1183 res.unlock();
1184
1185 if (indices != NULL) {
1186 indices[0] = indicesIdx;
1187 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1188 }
1189 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1190 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1191 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1192
1193 return JNI_TRUE;
1194}
1195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001197 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 jint defStyleAttr,
1199 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001200 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 jintArray attrs,
1202 jintArray outValues,
1203 jintArray outIndices)
1204{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001205 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001206 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001207 return JNI_FALSE;
1208 }
1209 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001210 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001211 return JNI_FALSE;
1212 }
1213 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001214 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 return JNI_FALSE;
1216 }
1217
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001218 DEBUG_STYLES(ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001219 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001220
Ashok Bhat896043d2014-01-17 16:02:38 +00001221 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001223 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001224 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001225 Res_value value;
1226
1227 const jsize NI = env->GetArrayLength(attrs);
1228 const jsize NV = env->GetArrayLength(outValues);
1229 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001230 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 return JNI_FALSE;
1232 }
1233
1234 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1235 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 return JNI_FALSE;
1237 }
1238
1239 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1240 jint* dest = baseDest;
1241 if (dest == NULL) {
1242 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 return JNI_FALSE;
1244 }
1245
1246 jint* indices = NULL;
1247 int indicesIdx = 0;
1248 if (outIndices != NULL) {
1249 if (env->GetArrayLength(outIndices) > NI) {
1250 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1251 }
1252 }
1253
1254 // Load default style from attribute, if specified...
1255 uint32_t defStyleBagTypeSetFlags = 0;
1256 if (defStyleAttr != 0) {
1257 Res_value value;
1258 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1259 if (value.dataType == Res_value::TYPE_REFERENCE) {
1260 defStyleRes = value.data;
1261 }
1262 }
1263 }
1264
1265 // Retrieve the style class associated with the current XML tag.
1266 int style = 0;
1267 uint32_t styleBagTypeSetFlags = 0;
1268 if (xmlParser != NULL) {
1269 ssize_t idx = xmlParser->indexOfStyle();
1270 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1271 if (value.dataType == value.TYPE_ATTRIBUTE) {
1272 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1273 value.dataType = Res_value::TYPE_NULL;
1274 }
1275 }
1276 if (value.dataType == value.TYPE_REFERENCE) {
1277 style = value.data;
1278 }
1279 }
1280 }
1281
1282 // Now lock down the resource object and start pulling stuff from it.
1283 res.lock();
1284
1285 // Retrieve the default style bag, if requested.
1286 const ResTable::bag_entry* defStyleEnt = NULL;
1287 uint32_t defStyleTypeSetFlags = 0;
1288 ssize_t bagOff = defStyleRes != 0
1289 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1290 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1291 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1292 (bagOff >= 0 ? bagOff : 0);
1293
1294 // Retrieve the style class bag, if requested.
1295 const ResTable::bag_entry* styleEnt = NULL;
1296 uint32_t styleTypeSetFlags = 0;
1297 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1298 styleTypeSetFlags |= styleBagTypeSetFlags;
1299 const ResTable::bag_entry* endStyleEnt = styleEnt +
1300 (bagOff >= 0 ? bagOff : 0);
1301
1302 // Retrieve the XML attributes, if requested.
1303 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1304 jsize ix=0;
1305 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1306
1307 static const ssize_t kXmlBlock = 0x10000000;
1308
1309 // Now iterate through all of the attributes that the client has requested,
1310 // filling in each with whatever data we can find.
1311 ssize_t block = 0;
1312 uint32_t typeSetFlags;
1313 for (jsize ii=0; ii<NI; ii++) {
1314 const uint32_t curIdent = (uint32_t)src[ii];
1315
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001316 DEBUG_STYLES(ALOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001318 // Try to find a value for this attribute... we prioritize values
1319 // coming from, first XML attributes, then XML style, then default
1320 // style, and finally the theme.
1321 value.dataType = Res_value::TYPE_NULL;
1322 value.data = 0;
1323 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001324 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325
1326 // Skip through XML attributes until the end or the next possible match.
1327 while (ix < NX && curIdent > curXmlAttr) {
1328 ix++;
1329 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1330 }
1331 // Retrieve the current XML attribute if it matches, and step to next.
1332 if (ix < NX && curIdent == curXmlAttr) {
1333 block = kXmlBlock;
1334 xmlParser->getAttributeValue(ix, &value);
1335 ix++;
1336 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001337 DEBUG_STYLES(ALOGI("-> From XML: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001338 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 }
1340
1341 // Skip through the style values until the end or the next possible match.
1342 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
1343 styleEnt++;
1344 }
1345 // Retrieve the current style attribute if it matches, and step to next.
1346 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1347 if (value.dataType == Res_value::TYPE_NULL) {
1348 block = styleEnt->stringBlock;
1349 typeSetFlags = styleTypeSetFlags;
1350 value = styleEnt->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001351 DEBUG_STYLES(ALOGI("-> From style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001352 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 }
1354 styleEnt++;
1355 }
1356
1357 // Skip through the default style values until the end or the next possible match.
1358 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1359 defStyleEnt++;
1360 }
1361 // Retrieve the current default style attribute if it matches, and step to next.
1362 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1363 if (value.dataType == Res_value::TYPE_NULL) {
1364 block = defStyleEnt->stringBlock;
1365 typeSetFlags = defStyleTypeSetFlags;
1366 value = defStyleEnt->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001367 DEBUG_STYLES(ALOGI("-> From def style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001368 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 }
1370 defStyleEnt++;
1371 }
1372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 uint32_t resid = 0;
1374 if (value.dataType != Res_value::TYPE_NULL) {
1375 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001376 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1377 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001379 DEBUG_STYLES(ALOGI("-> Resolved attr: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001380 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 } else {
1382 // If we still don't have a value for this attribute, try to find
1383 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1385 if (newBlock >= 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001386 DEBUG_STYLES(ALOGI("-> From theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001387 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001388 newBlock = res.resolveReference(&value, block, &resid,
1389 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001390#if THROW_ON_BAD_ID
1391 if (newBlock == BAD_INDEX) {
1392 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1393 return JNI_FALSE;
1394 }
1395#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001397 DEBUG_STYLES(ALOGI("-> Resolved theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001398 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 }
1400 }
1401
1402 // Deal with the special @null value -- it turns back to TYPE_NULL.
1403 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001404 DEBUG_STYLES(ALOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001406 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407 }
1408
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001409 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001410 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411
1412 // Write the final value back to Java.
1413 dest[STYLE_TYPE] = value.dataType;
1414 dest[STYLE_DATA] = value.data;
1415 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001416 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 dest[STYLE_RESOURCE_ID] = resid;
1418 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001419 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1422 indicesIdx++;
1423 indices[indicesIdx] = ii;
1424 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 dest += STYLE_NUM_ENTRIES;
1427 }
1428
1429 res.unlock();
1430
1431 if (indices != NULL) {
1432 indices[0] = indicesIdx;
1433 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1434 }
1435 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1436 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1437
1438 return JNI_TRUE;
1439}
1440
1441static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001442 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 jintArray attrs,
1444 jintArray outValues,
1445 jintArray outIndices)
1446{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001447 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001448 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001449 return JNI_FALSE;
1450 }
1451 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001452 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001453 return JNI_FALSE;
1454 }
1455 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001456 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 return JNI_FALSE;
1458 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 AssetManager* am = assetManagerForJavaObject(env, clazz);
1461 if (am == NULL) {
1462 return JNI_FALSE;
1463 }
1464 const ResTable& res(am->getResources());
1465 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001466 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 const jsize NI = env->GetArrayLength(attrs);
1470 const jsize NV = env->GetArrayLength(outValues);
1471 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001472 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 return JNI_FALSE;
1474 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1477 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 return JNI_FALSE;
1479 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1482 jint* dest = baseDest;
1483 if (dest == NULL) {
1484 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 return JNI_FALSE;
1486 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 jint* indices = NULL;
1489 int indicesIdx = 0;
1490 if (outIndices != NULL) {
1491 if (env->GetArrayLength(outIndices) > NI) {
1492 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1493 }
1494 }
1495
1496 // Now lock down the resource object and start pulling stuff from it.
1497 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 // Retrieve the XML attributes, if requested.
1500 const jsize NX = xmlParser->getAttributeCount();
1501 jsize ix=0;
1502 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 // Now iterate through all of the attributes that the client has requested,
1507 // filling in each with whatever data we can find.
1508 ssize_t block = 0;
1509 uint32_t typeSetFlags;
1510 for (jsize ii=0; ii<NI; ii++) {
1511 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 // Try to find a value for this attribute...
1514 value.dataType = Res_value::TYPE_NULL;
1515 value.data = 0;
1516 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001517 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 // Skip through XML attributes until the end or the next possible match.
1520 while (ix < NX && curIdent > curXmlAttr) {
1521 ix++;
1522 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1523 }
1524 // Retrieve the current XML attribute if it matches, and step to next.
1525 if (ix < NX && curIdent == curXmlAttr) {
1526 block = kXmlBlock;
1527 xmlParser->getAttributeValue(ix, &value);
1528 ix++;
1529 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1530 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1533 uint32_t resid = 0;
1534 if (value.dataType != Res_value::TYPE_NULL) {
1535 // Take care of resolving the found resource to its final value.
1536 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001537 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1538 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001539#if THROW_ON_BAD_ID
1540 if (newBlock == BAD_INDEX) {
1541 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1542 return JNI_FALSE;
1543 }
1544#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 if (newBlock >= 0) block = newBlock;
1546 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 // Deal with the special @null value -- it turns back to TYPE_NULL.
1549 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1550 value.dataType = Res_value::TYPE_NULL;
1551 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 // Write the final value back to Java.
1556 dest[STYLE_TYPE] = value.dataType;
1557 dest[STYLE_DATA] = value.data;
1558 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001559 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 dest[STYLE_RESOURCE_ID] = resid;
1561 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001562 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1565 indicesIdx++;
1566 indices[indicesIdx] = ii;
1567 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 dest += STYLE_NUM_ENTRIES;
1570 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 if (indices != NULL) {
1575 indices[0] = indicesIdx;
1576 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1577 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1580 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 return JNI_TRUE;
1583}
1584
1585static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1586 jint id)
1587{
1588 AssetManager* am = assetManagerForJavaObject(env, clazz);
1589 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001590 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 }
1592 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 res.lock();
1595 const ResTable::bag_entry* defStyleEnt = NULL;
1596 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1597 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001598
Ashok Bhat896043d2014-01-17 16:02:38 +00001599 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600}
1601
1602static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1603 jint id,
1604 jintArray outValues)
1605{
1606 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 return JNI_FALSE;
1609 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 AssetManager* am = assetManagerForJavaObject(env, clazz);
1612 if (am == NULL) {
1613 return JNI_FALSE;
1614 }
1615 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001616 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 Res_value value;
1618 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1623 jint* dest = baseDest;
1624 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001625 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 return JNI_FALSE;
1627 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 // Now lock down the resource object and start pulling stuff from it.
1630 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 const ResTable::bag_entry* arrayEnt = NULL;
1633 uint32_t arrayTypeSetFlags = 0;
1634 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1635 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1636 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 int i = 0;
1639 uint32_t typeSetFlags;
1640 while (i < NV && arrayEnt < endArrayEnt) {
1641 block = arrayEnt->stringBlock;
1642 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001643 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 uint32_t resid = 0;
1647 if (value.dataType != Res_value::TYPE_NULL) {
1648 // Take care of resolving the found resource to its final value.
1649 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001650 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1651 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001652#if THROW_ON_BAD_ID
1653 if (newBlock == BAD_INDEX) {
1654 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1655 return JNI_FALSE;
1656 }
1657#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 if (newBlock >= 0) block = newBlock;
1659 }
1660
1661 // Deal with the special @null value -- it turns back to TYPE_NULL.
1662 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1663 value.dataType = Res_value::TYPE_NULL;
1664 }
1665
1666 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1667
1668 // Write the final value back to Java.
1669 dest[STYLE_TYPE] = value.dataType;
1670 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001671 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 dest[STYLE_RESOURCE_ID] = resid;
1673 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001674 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 dest += STYLE_NUM_ENTRIES;
1676 i+= STYLE_NUM_ENTRIES;
1677 arrayEnt++;
1678 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001686 return i;
1687}
1688
Ashok Bhat896043d2014-01-17 16:02:38 +00001689static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 jint cookie,
1691 jstring fileName)
1692{
1693 AssetManager* am = assetManagerForJavaObject(env, clazz);
1694 if (am == NULL) {
1695 return 0;
1696 }
1697
Steve Block71f2cf12011-10-20 11:56:00 +01001698 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700 ScopedUtfChars fileName8(env, fileName);
1701 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 return 0;
1703 }
1704
Adam Lesinskide898ff2014-01-29 18:20:45 -08001705 int32_t assetCookie = static_cast<int32_t>(cookie);
1706 Asset* a = assetCookie
1707 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1708 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709
1710 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001711 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 return 0;
1713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714
Adam Lesinskide898ff2014-01-29 18:20:45 -08001715 const DynamicRefTable* dynamicRefTable =
1716 am->getResources().getDynamicRefTableForCookie(assetCookie);
1717 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1719 a->close();
1720 delete a;
1721
1722 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001723 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724 return 0;
1725 }
1726
Ashok Bhat896043d2014-01-17 16:02:38 +00001727 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728}
1729
1730static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1731 jint arrayResId)
1732{
1733 AssetManager* am = assetManagerForJavaObject(env, clazz);
1734 if (am == NULL) {
1735 return NULL;
1736 }
1737 const ResTable& res(am->getResources());
1738
1739 const ResTable::bag_entry* startOfBag;
1740 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1741 if (N < 0) {
1742 return NULL;
1743 }
1744
1745 jintArray array = env->NewIntArray(N * 2);
1746 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 res.unlockBag(startOfBag);
1748 return NULL;
1749 }
1750
1751 Res_value value;
1752 const ResTable::bag_entry* bag = startOfBag;
1753 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1754 jint stringIndex = -1;
1755 jint stringBlock = 0;
1756 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 // Take care of resolving the found resource to its final value.
1759 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1760 if (value.dataType == Res_value::TYPE_STRING) {
1761 stringIndex = value.data;
1762 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001763
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001764#if THROW_ON_BAD_ID
1765 if (stringBlock == BAD_INDEX) {
1766 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1767 return array;
1768 }
1769#endif
Elliott Hughes69a017b2011-04-08 14:10:28 -07001770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 //todo: It might be faster to allocate a C array to contain
1772 // the blocknums and indices, put them in there and then
1773 // do just one SetIntArrayRegion()
1774 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1775 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1776 j = j + 2;
1777 }
1778 res.unlockBag(startOfBag);
1779 return array;
1780}
1781
1782static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1783 jint arrayResId)
1784{
1785 AssetManager* am = assetManagerForJavaObject(env, clazz);
1786 if (am == NULL) {
1787 return NULL;
1788 }
1789 const ResTable& res(am->getResources());
1790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 const ResTable::bag_entry* startOfBag;
1792 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1793 if (N < 0) {
1794 return NULL;
1795 }
1796
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001797 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001798 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001799 res.unlockBag(startOfBag);
1800 return NULL;
1801 }
1802
1803 Res_value value;
1804 const ResTable::bag_entry* bag = startOfBag;
1805 size_t strLen = 0;
1806 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1807 value = bag->map.value;
1808 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001810 // Take care of resolving the found resource to its final value.
1811 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001812#if THROW_ON_BAD_ID
1813 if (block == BAD_INDEX) {
1814 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1815 return array;
1816 }
1817#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001819 const ResStringPool* pool = res.getTableStringBlock(block);
1820 const char* str8 = pool->string8At(value.data, &strLen);
1821 if (str8 != NULL) {
1822 str = env->NewStringUTF(str8);
1823 } else {
1824 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1825 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001826 }
1827
1828 // If one of our NewString{UTF} calls failed due to memory, an
1829 // exception will be pending.
1830 if (env->ExceptionCheck()) {
1831 res.unlockBag(startOfBag);
1832 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 }
Kenny Root780d2a12010-02-22 22:36:26 -08001834
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001835 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001836
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001837 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1838 // If we have a large amount of strings in our array, we might
1839 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001840 env->DeleteLocalRef(str);
1841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001842 }
1843 res.unlockBag(startOfBag);
1844 return array;
1845}
1846
1847static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1848 jint arrayResId)
1849{
1850 AssetManager* am = assetManagerForJavaObject(env, clazz);
1851 if (am == NULL) {
1852 return NULL;
1853 }
1854 const ResTable& res(am->getResources());
1855
1856 const ResTable::bag_entry* startOfBag;
1857 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1858 if (N < 0) {
1859 return NULL;
1860 }
1861
1862 jintArray array = env->NewIntArray(N);
1863 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 res.unlockBag(startOfBag);
1865 return NULL;
1866 }
1867
1868 Res_value value;
1869 const ResTable::bag_entry* bag = startOfBag;
1870 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1871 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 // Take care of resolving the found resource to its final value.
1874 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001875#if THROW_ON_BAD_ID
1876 if (block == BAD_INDEX) {
1877 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1878 return array;
1879 }
1880#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 if (value.dataType >= Res_value::TYPE_FIRST_INT
1882 && value.dataType <= Res_value::TYPE_LAST_INT) {
1883 int intVal = value.data;
1884 env->SetIntArrayRegion(array, i, 1, &intVal);
1885 }
1886 }
1887 res.unlockBag(startOfBag);
1888 return array;
1889}
1890
Jon Miranda042ad632014-09-03 17:57:35 -07001891static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1892 jint styleId)
1893{
1894 AssetManager* am = assetManagerForJavaObject(env, clazz);
1895 if (am == NULL) {
1896 return NULL;
1897 }
1898 const ResTable& res(am->getResources());
1899
1900 const ResTable::bag_entry* startOfBag;
1901 const ssize_t N = res.lockBag(styleId, &startOfBag);
1902 if (N < 0) {
1903 return NULL;
1904 }
1905
1906 jintArray array = env->NewIntArray(N);
1907 if (array == NULL) {
1908 res.unlockBag(startOfBag);
1909 return NULL;
1910 }
1911
1912 Res_value value;
1913 const ResTable::bag_entry* bag = startOfBag;
1914 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1915 int resourceId = bag->map.name.ident;
1916 env->SetIntArrayRegion(array, i, 1, &resourceId);
1917 }
1918 res.unlockBag(startOfBag);
1919 return array;
1920}
1921
Mårten Kongstad48d22322014-01-31 14:43:27 +01001922static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001924 if (isSystem) {
1925 verifySystemIdmaps();
1926 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001927 AssetManager* am = new AssetManager();
1928 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001929 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 return;
1931 }
1932
1933 am->addDefaultAssets();
1934
Steve Block71f2cf12011-10-20 11:56:00 +01001935 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001936 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937}
1938
1939static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1940{
1941 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001942 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001943 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001944 if (am != NULL) {
1945 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001946 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 }
1948}
1949
1950static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1951{
1952 return Asset::getGlobalCount();
1953}
1954
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001955static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1956{
1957 String8 alloc = Asset::getAssetAllocations();
1958 if (alloc.length() <= 0) {
1959 return NULL;
1960 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001961
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001962 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001963 return str;
1964}
1965
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1967{
1968 return AssetManager::getGlobalCount();
1969}
1970
1971// ----------------------------------------------------------------------------
1972
1973/*
1974 * JNI registration.
1975 */
1976static JNINativeMethod gAssetManagerMethods[] = {
1977 /* name, signature, funcPtr */
1978
1979 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00001980 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 (void*) android_content_AssetManager_openAsset },
1982 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1983 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00001984 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001985 (void*) android_content_AssetManager_openNonAssetNative },
1986 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1987 (void*) android_content_AssetManager_openNonAssetFdNative },
1988 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1989 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00001990 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001992 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00001994 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001996 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001998 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002000 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002002 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002004 { "addOverlayPath", "(Ljava/lang/String;)I",
2005 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 { "isUpToDate", "()Z",
2007 (void*) android_content_AssetManager_isUpToDate },
2008
2009 // Resources.
2010 { "setLocale", "(Ljava/lang/String;)V",
2011 (void*) android_content_AssetManager_setLocale },
2012 { "getLocales", "()[Ljava/lang/String;",
2013 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002014 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 (void*) android_content_AssetManager_setConfiguration },
2016 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2017 (void*) android_content_AssetManager_getResourceIdentifier },
2018 { "getResourceName","(I)Ljava/lang/String;",
2019 (void*) android_content_AssetManager_getResourceName },
2020 { "getResourcePackageName","(I)Ljava/lang/String;",
2021 (void*) android_content_AssetManager_getResourcePackageName },
2022 { "getResourceTypeName","(I)Ljava/lang/String;",
2023 (void*) android_content_AssetManager_getResourceTypeName },
2024 { "getResourceEntryName","(I)Ljava/lang/String;",
2025 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002026 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 (void*) android_content_AssetManager_loadResourceValue },
2028 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2029 (void*) android_content_AssetManager_loadResourceBagValue },
2030 { "getStringBlockCount","()I",
2031 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002032 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 (void*) android_content_AssetManager_getNativeStringBlock },
2034 { "getCookieName","(I)Ljava/lang/String;",
2035 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002036 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2037 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038
2039 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002040 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002042 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002044 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002046 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002048 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002050 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002052 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_applyStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002054 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_retrieveAttributes },
2056 { "getArraySize","(I)I",
2057 (void*) android_content_AssetManager_getArraySize },
2058 { "retrieveArray","(I[I)I",
2059 (void*) android_content_AssetManager_retrieveArray },
2060
2061 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002062 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 (void*) android_content_AssetManager_openXmlAssetNative },
2064
2065 // Arrays.
2066 { "getArrayStringResource","(I)[Ljava/lang/String;",
2067 (void*) android_content_AssetManager_getArrayStringResource },
2068 { "getArrayStringInfo","(I)[I",
2069 (void*) android_content_AssetManager_getArrayStringInfo },
2070 { "getArrayIntResource","(I)[I",
2071 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002072 { "getStyleAttributes","(I)[I",
2073 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074
2075 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002076 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_init },
2078 { "destroy", "()V",
2079 (void*) android_content_AssetManager_destroy },
2080 { "getGlobalAssetCount", "()I",
2081 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002082 { "getAssetAllocations", "()Ljava/lang/String;",
2083 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 { "getGlobalAssetManagerCount", "()I",
2085 (void*) android_content_AssetManager_getGlobalAssetCount },
2086};
2087
2088int register_android_content_AssetManager(JNIEnv* env)
2089{
2090 jclass typedValue = env->FindClass("android/util/TypedValue");
2091 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
2092 gTypedValueOffsets.mType
2093 = env->GetFieldID(typedValue, "type", "I");
2094 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
2095 gTypedValueOffsets.mData
2096 = env->GetFieldID(typedValue, "data", "I");
2097 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
2098 gTypedValueOffsets.mString
2099 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
2100 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
2101 gTypedValueOffsets.mAssetCookie
2102 = env->GetFieldID(typedValue, "assetCookie", "I");
2103 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
2104 gTypedValueOffsets.mResourceId
2105 = env->GetFieldID(typedValue, "resourceId", "I");
2106 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
2107 gTypedValueOffsets.mChangingConfigurations
2108 = env->GetFieldID(typedValue, "changingConfigurations", "I");
2109 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
2110 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
2111 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
2112
2113 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
2114 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
2115 gAssetFileDescriptorOffsets.mFd
2116 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
2117 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
2118 gAssetFileDescriptorOffsets.mStartOffset
2119 = env->GetFieldID(assetFd, "mStartOffset", "J");
2120 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
2121 gAssetFileDescriptorOffsets.mLength
2122 = env->GetFieldID(assetFd, "mLength", "J");
2123 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
2124
2125 jclass assetManager = env->FindClass("android/content/res/AssetManager");
2126 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
2127 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00002128 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
2130
Carl Shapiroc1318ba2011-03-03 14:22:28 -08002131 jclass stringClass = env->FindClass("java/lang/String");
2132 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
2133 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01002134 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 -08002135
Adam Lesinskide898ff2014-01-29 18:20:45 -08002136 jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
2137 LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
2138 gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
2139 gSparseArrayOffsets.constructor =
2140 env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
2141 LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
2142 gSparseArrayOffsets.put =
2143 env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
2144 LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
2145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 return AndroidRuntime::registerNativeMethods(env,
2147 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
2148}
2149
2150}; // namespace android