blob: 683b4c490ec39f124616c5d9bbcf7a63e3c4c75e [file] [log] [blame]
Adam Lesinskibde1df22018-02-09 11:12:22 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** 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
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** 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
15** limitations under the License.
16*/
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017
18#define LOG_TAG "asset"
19
Adam Lesinskibde1df22018-02-09 11:12:22 -080020#include <android_runtime/android_util_AssetManager.h>
21
Dan Albert46d84442014-11-18 16:07:51 -080022#include <inttypes.h>
23#include <linux/capability.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <stdio.h>
Adam Lesinski11875902017-01-23 12:58:11 -080025#include <sys/types.h>
26#include <sys/wait.h>
Adam Lesinskibde1df22018-02-09 11:12:22 -080027#include <sys/stat.h>
28#include <sys/system_properties.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010029
Dan Albert46d84442014-11-18 16:07:51 -080030#include <private/android_filesystem_config.h> // for AID_SYSTEM
31
Adam Lesinski11875902017-01-23 12:58:11 -080032#include "androidfw/Asset.h"
33#include "androidfw/AssetManager.h"
Adam Lesinski11875902017-01-23 12:58:11 -080034#include "androidfw/AttributeResolution.h"
Adam Lesinski11875902017-01-23 12:58:11 -080035#include "androidfw/ResourceTypes.h"
Adam Lesinskibde1df22018-02-09 11:12:22 -080036#include "android_runtime/AndroidRuntime.h"
37#include "android_util_Binder.h"
Dan Albert3a091b72014-11-20 15:41:25 -080038#include "core_jni_helpers.h"
39#include "jni.h"
Adam Lesinskibde1df22018-02-09 11:12:22 -080040#include <nativehelper/JNIHelp.h>
41#include <nativehelper/ScopedStringChars.h>
42#include <nativehelper/ScopedUtfChars.h>
Dan Albert46d84442014-11-18 16:07:51 -080043#include "utils/Log.h"
Adam Lesinski11875902017-01-23 12:58:11 -080044#include "utils/misc.h"
Adam Lesinskibde1df22018-02-09 11:12:22 -080045#include "utils/String8.h"
Dan Albert46d84442014-11-18 16:07:51 -080046
Mårten Kongstad48d22322014-01-31 14:43:27 +010047extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
48extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
51namespace android {
52
Adam Lesinskibde1df22018-02-09 11:12:22 -080053static const bool kThrowOnBadId = false;
54
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055// ----------------------------------------------------------------------------
56
Adam Lesinskibde1df22018-02-09 11:12:22 -080057static struct typedvalue_offsets_t
58{
59 jfieldID mType;
60 jfieldID mData;
61 jfieldID mString;
62 jfieldID mAssetCookie;
63 jfieldID mResourceId;
64 jfieldID mChangingConfigurations;
65 jfieldID mDensity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066} gTypedValueOffsets;
67
Adam Lesinskibde1df22018-02-09 11:12:22 -080068static struct assetfiledescriptor_offsets_t
69{
70 jfieldID mFd;
71 jfieldID mStartOffset;
72 jfieldID mLength;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073} gAssetFileDescriptorOffsets;
74
Adam Lesinskibde1df22018-02-09 11:12:22 -080075static struct assetmanager_offsets_t
76{
77 jfieldID mObject;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078} gAssetManagerOffsets;
79
Adam Lesinskibde1df22018-02-09 11:12:22 -080080static struct sparsearray_offsets_t
81{
82 jclass classObject;
83 jmethodID constructor;
84 jmethodID put;
Adam Lesinskide898ff2014-01-29 18:20:45 -080085} gSparseArrayOffsets;
86
Adam Lesinskibde1df22018-02-09 11:12:22 -080087static struct configuration_offsets_t
88{
89 jclass classObject;
90 jmethodID constructor;
91 jfieldID mSmallestScreenWidthDpOffset;
92 jfieldID mScreenWidthDpOffset;
93 jfieldID mScreenHeightDpOffset;
Filip Gruszczynski23493322015-07-29 17:02:59 -070094} gConfigurationOffsets;
95
Adam Lesinskibde1df22018-02-09 11:12:22 -080096jclass g_stringClass = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
98// ----------------------------------------------------------------------------
99
Adam Lesinskibde1df22018-02-09 11:12:22 -0800100static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
101 const Res_value& value, uint32_t ref, ssize_t block,
102 uint32_t typeSpecFlags, ResTable_config* config = NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103
Adam Lesinskibde1df22018-02-09 11:12:22 -0800104jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
105 const Res_value& value, uint32_t ref, ssize_t block,
106 uint32_t typeSpecFlags, ResTable_config* config)
107{
108 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
109 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
110 static_cast<jint>(table->getTableCookie(block)));
111 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
112 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
113 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
114 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
115 typeSpecFlags);
116 if (config != NULL) {
117 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
118 }
119 return block;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120}
121
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900122// This is called by zygote (running as user root) as part of preloadResources.
Adam Lesinskibde1df22018-02-09 11:12:22 -0800123static void verifySystemIdmaps()
124{
125 pid_t pid;
126 char system_id[10];
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900127
Adam Lesinskibde1df22018-02-09 11:12:22 -0800128 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900129
Adam Lesinskibde1df22018-02-09 11:12:22 -0800130 switch (pid = fork()) {
131 case -1:
132 ALOGE("failed to fork for idmap: %s", strerror(errno));
133 break;
134 case 0: // child
135 {
136 struct __user_cap_header_struct capheader;
137 struct __user_cap_data_struct capdata;
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900138
Adam Lesinskibde1df22018-02-09 11:12:22 -0800139 memset(&capheader, 0, sizeof(capheader));
140 memset(&capdata, 0, sizeof(capdata));
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900141
Adam Lesinskibde1df22018-02-09 11:12:22 -0800142 capheader.version = _LINUX_CAPABILITY_VERSION;
143 capheader.pid = 0;
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900144
Adam Lesinskibde1df22018-02-09 11:12:22 -0800145 if (capget(&capheader, &capdata) != 0) {
146 ALOGE("capget: %s\n", strerror(errno));
147 exit(1);
148 }
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900149
Adam Lesinskibde1df22018-02-09 11:12:22 -0800150 capdata.effective = capdata.permitted;
151 if (capset(&capheader, &capdata) != 0) {
152 ALOGE("capset: %s\n", strerror(errno));
153 exit(1);
154 }
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900155
Adam Lesinskibde1df22018-02-09 11:12:22 -0800156 if (setgid(AID_SYSTEM) != 0) {
157 ALOGE("setgid: %s\n", strerror(errno));
158 exit(1);
159 }
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900160
Adam Lesinskibde1df22018-02-09 11:12:22 -0800161 if (setuid(AID_SYSTEM) != 0) {
162 ALOGE("setuid: %s\n", strerror(errno));
163 exit(1);
164 }
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900165
Adam Lesinskibde1df22018-02-09 11:12:22 -0800166 // Generic idmap parameters
167 const char* argv[8];
168 int argc = 0;
169 struct stat st;
Jaekyun Seok7de2f9c2017-03-02 12:45:10 +0900170
Adam Lesinskibde1df22018-02-09 11:12:22 -0800171 memset(argv, NULL, sizeof(argv));
172 argv[argc++] = AssetManager::IDMAP_BIN;
173 argv[argc++] = "--scan";
174 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
175 argv[argc++] = AssetManager::TARGET_APK_PATH;
176 argv[argc++] = AssetManager::IDMAP_DIR;
Adam Lesinskidcb3c652017-01-23 12:58:11 -0800177
Adam Lesinskibde1df22018-02-09 11:12:22 -0800178 // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
179 // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
180 char subdir[PROP_VALUE_MAX];
181 int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
182 if (len > 0) {
183 String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
184 if (stat(overlayPath.string(), &st) == 0) {
185 argv[argc++] = overlayPath.string();
186 }
187 }
188 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
189 argv[argc++] = AssetManager::OVERLAY_DIR;
190 }
Adam Lesinskidcb3c652017-01-23 12:58:11 -0800191
Adam Lesinskibde1df22018-02-09 11:12:22 -0800192 if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
193 argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
194 }
Adam Lesinski11875902017-01-23 12:58:11 -0800195
Adam Lesinskibde1df22018-02-09 11:12:22 -0800196 // Finally, invoke idmap (if any overlay directory exists)
197 if (argc > 5) {
198 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
199 ALOGE("failed to execv for idmap: %s", strerror(errno));
200 exit(1); // should never get here
201 } else {
202 exit(0);
203 }
204 }
205 break;
206 default: // parent
207 waitpid(pid, NULL, 0);
208 break;
209 }
Adam Lesinskidcb3c652017-01-23 12:58:11 -0800210}
211
Adam Lesinskidcb3c652017-01-23 12:58:11 -0800212
213// ----------------------------------------------------------------------------
214
Adam Lesinskibde1df22018-02-09 11:12:22 -0800215// this guy is exported to other jni routines
216AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
217{
218 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
219 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
220 if (am != NULL) {
221 return am;
222 }
Adam Lesinski11875902017-01-23 12:58:11 -0800223 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
Adam Lesinskibde1df22018-02-09 11:12:22 -0800224 return NULL;
Adam Lesinski11875902017-01-23 12:58:11 -0800225}
Adam Lesinskidcb3c652017-01-23 12:58:11 -0800226
Adam Lesinskibde1df22018-02-09 11:12:22 -0800227static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
228 jstring fileName, jint mode)
229{
230 AssetManager* am = assetManagerForJavaObject(env, clazz);
231 if (am == NULL) {
232 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800233 }
234
Adam Lesinskibde1df22018-02-09 11:12:22 -0800235 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
Adam Lesinski11875902017-01-23 12:58:11 -0800236
Adam Lesinskibde1df22018-02-09 11:12:22 -0800237 ScopedUtfChars fileName8(env, fileName);
238 if (fileName8.c_str() == NULL) {
239 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
240 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800241 }
242
Adam Lesinskibde1df22018-02-09 11:12:22 -0800243 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
244 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
245 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
246 return -1;
247 }
248
249 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
250
251 if (a == NULL) {
252 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
253 return -1;
254 }
255
256 //printf("Created Asset Stream: %p\n", a);
257
258 return reinterpret_cast<jlong>(a);
Adam Lesinski11875902017-01-23 12:58:11 -0800259}
260
Adam Lesinskibde1df22018-02-09 11:12:22 -0800261static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
262{
263 off64_t startOffset, length;
264 int fd = a->openFileDescriptor(&startOffset, &length);
265 delete a;
Adam Lesinski11875902017-01-23 12:58:11 -0800266
Adam Lesinskibde1df22018-02-09 11:12:22 -0800267 if (fd < 0) {
268 jniThrowException(env, "java/io/FileNotFoundException",
269 "This file can not be opened as a file descriptor; it is probably compressed");
270 return NULL;
Adam Lesinskiec7f06c2018-02-09 11:01:26 -0800271 }
Adam Lesinskibde1df22018-02-09 11:12:22 -0800272
273 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
274 if (offsets == NULL) {
275 close(fd);
276 return NULL;
277 }
278
279 offsets[0] = startOffset;
280 offsets[1] = length;
281
282 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
283
284 jobject fileDesc = jniCreateFileDescriptor(env, fd);
285 if (fileDesc == NULL) {
286 close(fd);
287 return NULL;
288 }
289
290 return newParcelFileDescriptor(env, fileDesc);
291}
292
293static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
294 jstring fileName, jlongArray outOffsets)
295{
296 AssetManager* am = assetManagerForJavaObject(env, clazz);
297 if (am == NULL) {
298 return NULL;
299 }
300
301 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
302
303 ScopedUtfChars fileName8(env, fileName);
304 if (fileName8.c_str() == NULL) {
305 return NULL;
306 }
307
308 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
309
310 if (a == NULL) {
311 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
312 return NULL;
313 }
314
315 //printf("Created Asset Stream: %p\n", a);
316
317 return returnParcelFileDescriptor(env, a, outOffsets);
318}
319
320static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
321 jint cookie,
322 jstring fileName,
323 jint mode)
324{
325 AssetManager* am = assetManagerForJavaObject(env, clazz);
326 if (am == NULL) {
327 return 0;
328 }
329
330 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
331
332 ScopedUtfChars fileName8(env, fileName);
333 if (fileName8.c_str() == NULL) {
334 return -1;
335 }
336
337 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
338 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
339 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
340 return -1;
341 }
342
343 Asset* a = cookie
344 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
345 (Asset::AccessMode)mode)
346 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
347
348 if (a == NULL) {
349 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
350 return -1;
351 }
352
353 //printf("Created Asset Stream: %p\n", a);
354
355 return reinterpret_cast<jlong>(a);
356}
357
358static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
359 jint cookie,
360 jstring fileName,
361 jlongArray outOffsets)
362{
363 AssetManager* am = assetManagerForJavaObject(env, clazz);
364 if (am == NULL) {
365 return NULL;
366 }
367
368 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
369
370 ScopedUtfChars fileName8(env, fileName);
371 if (fileName8.c_str() == NULL) {
372 return NULL;
373 }
374
375 Asset* a = cookie
376 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
377 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
378
379 if (a == NULL) {
380 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
381 return NULL;
382 }
383
384 //printf("Created Asset Stream: %p\n", a);
385
386 return returnParcelFileDescriptor(env, a, outOffsets);
387}
388
389static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
390 jstring fileName)
391{
392 AssetManager* am = assetManagerForJavaObject(env, clazz);
393 if (am == NULL) {
394 return NULL;
395 }
396
397 ScopedUtfChars fileName8(env, fileName);
398 if (fileName8.c_str() == NULL) {
399 return NULL;
400 }
401
402 AssetDir* dir = am->openDir(fileName8.c_str());
403
404 if (dir == NULL) {
405 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
406 return NULL;
407 }
408
409 size_t N = dir->getFileCount();
410
411 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
412 g_stringClass, NULL);
413 if (array == NULL) {
414 delete dir;
415 return NULL;
416 }
417
418 for (size_t i=0; i<N; i++) {
419 const String8& name = dir->getFileName(i);
420 jstring str = env->NewStringUTF(name.string());
421 if (str == NULL) {
422 delete dir;
423 return NULL;
Adam Lesinskiec7f06c2018-02-09 11:01:26 -0800424 }
Adam Lesinskibde1df22018-02-09 11:12:22 -0800425 env->SetObjectArrayElement(array, i, str);
426 env->DeleteLocalRef(str);
Adam Lesinski11875902017-01-23 12:58:11 -0800427 }
428
Adam Lesinskibde1df22018-02-09 11:12:22 -0800429 delete dir;
Adam Lesinski11875902017-01-23 12:58:11 -0800430
Adam Lesinskibde1df22018-02-09 11:12:22 -0800431 return array;
Adam Lesinski11875902017-01-23 12:58:11 -0800432}
433
Adam Lesinskibde1df22018-02-09 11:12:22 -0800434static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
435 jlong assetHandle)
436{
437 Asset* a = reinterpret_cast<Asset*>(assetHandle);
Adam Lesinski11875902017-01-23 12:58:11 -0800438
Adam Lesinskibde1df22018-02-09 11:12:22 -0800439 //printf("Destroying Asset Stream: %p\n", a);
Adam Lesinski11875902017-01-23 12:58:11 -0800440
Adam Lesinskibde1df22018-02-09 11:12:22 -0800441 if (a == NULL) {
442 jniThrowNullPointerException(env, "asset");
443 return;
Adam Lesinski11875902017-01-23 12:58:11 -0800444 }
445
Adam Lesinskibde1df22018-02-09 11:12:22 -0800446 delete a;
Adam Lesinski11875902017-01-23 12:58:11 -0800447}
448
Adam Lesinskibde1df22018-02-09 11:12:22 -0800449static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
450 jlong assetHandle)
451{
452 Asset* a = reinterpret_cast<Asset*>(assetHandle);
Adam Lesinski11875902017-01-23 12:58:11 -0800453
Adam Lesinskibde1df22018-02-09 11:12:22 -0800454 if (a == NULL) {
455 jniThrowNullPointerException(env, "asset");
456 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800457 }
458
Adam Lesinskibde1df22018-02-09 11:12:22 -0800459 uint8_t b;
460 ssize_t res = a->read(&b, 1);
461 return res == 1 ? b : -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800462}
463
Adam Lesinskibde1df22018-02-09 11:12:22 -0800464static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
465 jlong assetHandle, jbyteArray bArray,
466 jint off, jint len)
467{
468 Asset* a = reinterpret_cast<Asset*>(assetHandle);
Adam Lesinski11875902017-01-23 12:58:11 -0800469
Adam Lesinskibde1df22018-02-09 11:12:22 -0800470 if (a == NULL || bArray == NULL) {
471 jniThrowNullPointerException(env, "asset");
472 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800473 }
474
Adam Lesinskibde1df22018-02-09 11:12:22 -0800475 if (len == 0) {
476 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800477 }
Adam Lesinski11875902017-01-23 12:58:11 -0800478
Adam Lesinskibde1df22018-02-09 11:12:22 -0800479 jsize bLen = env->GetArrayLength(bArray);
480 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
481 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
482 return -1;
483 }
484
485 jbyte* b = env->GetByteArrayElements(bArray, NULL);
486 ssize_t res = a->read(b+off, len);
487 env->ReleaseByteArrayElements(bArray, b, 0);
488
489 if (res > 0) return static_cast<jint>(res);
490
491 if (res < 0) {
492 jniThrowException(env, "java/io/IOException", "");
493 }
Adam Lesinski11875902017-01-23 12:58:11 -0800494 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800495}
496
Adam Lesinskibde1df22018-02-09 11:12:22 -0800497static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
498 jlong assetHandle,
499 jlong offset, jint whence)
500{
501 Asset* a = reinterpret_cast<Asset*>(assetHandle);
Adam Lesinski11875902017-01-23 12:58:11 -0800502
Adam Lesinskibde1df22018-02-09 11:12:22 -0800503 if (a == NULL) {
504 jniThrowNullPointerException(env, "asset");
505 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800506 }
507
Adam Lesinskibde1df22018-02-09 11:12:22 -0800508 return a->seek(
509 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
510}
511
512static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
513 jlong assetHandle)
514{
515 Asset* a = reinterpret_cast<Asset*>(assetHandle);
516
517 if (a == NULL) {
518 jniThrowNullPointerException(env, "asset");
519 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800520 }
521
Adam Lesinskibde1df22018-02-09 11:12:22 -0800522 return a->getLength();
Adam Lesinski11875902017-01-23 12:58:11 -0800523}
524
Adam Lesinskibde1df22018-02-09 11:12:22 -0800525static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
526 jlong assetHandle)
527{
528 Asset* a = reinterpret_cast<Asset*>(assetHandle);
Adam Lesinski11875902017-01-23 12:58:11 -0800529
Adam Lesinskibde1df22018-02-09 11:12:22 -0800530 if (a == NULL) {
531 jniThrowNullPointerException(env, "asset");
532 return -1;
Adam Lesinski11875902017-01-23 12:58:11 -0800533 }
534
Adam Lesinskibde1df22018-02-09 11:12:22 -0800535 return a->getRemainingLength();
536}
Adam Lesinski11875902017-01-23 12:58:11 -0800537
Adam Lesinskibde1df22018-02-09 11:12:22 -0800538static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
539 jstring path, jboolean appAsLib)
540{
541 ScopedUtfChars path8(env, path);
542 if (path8.c_str() == NULL) {
543 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800544 }
545
Adam Lesinskibde1df22018-02-09 11:12:22 -0800546 AssetManager* am = assetManagerForJavaObject(env, clazz);
547 if (am == NULL) {
548 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800549 }
550
Adam Lesinskibde1df22018-02-09 11:12:22 -0800551 int32_t cookie;
552 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
553
554 return (res) ? static_cast<jint>(cookie) : 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800555}
556
Adam Lesinskibde1df22018-02-09 11:12:22 -0800557static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
558 jstring idmapPath)
559{
560 ScopedUtfChars idmapPath8(env, idmapPath);
561 if (idmapPath8.c_str() == NULL) {
562 return 0;
563 }
Adam Lesinski11875902017-01-23 12:58:11 -0800564
Adam Lesinskibde1df22018-02-09 11:12:22 -0800565 AssetManager* am = assetManagerForJavaObject(env, clazz);
566 if (am == NULL) {
567 return 0;
568 }
Adam Lesinski11875902017-01-23 12:58:11 -0800569
Adam Lesinskibde1df22018-02-09 11:12:22 -0800570 int32_t cookie;
571 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
Adam Lesinski11875902017-01-23 12:58:11 -0800572
Adam Lesinskibde1df22018-02-09 11:12:22 -0800573 return (res) ? (jint)cookie : 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800574}
575
Adam Lesinskibde1df22018-02-09 11:12:22 -0800576static jint android_content_AssetManager_addAssetFd(JNIEnv* env, jobject clazz,
577 jobject fileDescriptor, jstring debugPathName,
578 jboolean appAsLib)
579{
580 ScopedUtfChars debugPathName8(env, debugPathName);
Adam Lesinski11875902017-01-23 12:58:11 -0800581
Adam Lesinskibde1df22018-02-09 11:12:22 -0800582 int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
583 if (fd < 0) {
584 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad FileDescriptor");
585 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800586 }
Adam Lesinski11875902017-01-23 12:58:11 -0800587
Adam Lesinskibde1df22018-02-09 11:12:22 -0800588 AssetManager* am = assetManagerForJavaObject(env, clazz);
589 if (am == NULL) {
590 return 0;
Adam Lesinski11875902017-01-23 12:58:11 -0800591 }
Adam Lesinski11875902017-01-23 12:58:11 -0800592
Adam Lesinskibde1df22018-02-09 11:12:22 -0800593 int dupfd = ::dup(fd);
594 if (dupfd < 0) {
595 jniThrowIOException(env, errno);
596 return 0;
597 }
598
599 int32_t cookie;
600 bool res = am->addAssetFd(dupfd, String8(debugPathName8.c_str()), &cookie, appAsLib);
601
602 return (res) ? static_cast<jint>(cookie) : 0;
603}
604
605static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
606{
607 AssetManager* am = assetManagerForJavaObject(env, clazz);
608 if (am == NULL) {
609 return JNI_TRUE;
610 }
611 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
612}
613
614static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
615{
616 Vector<String8> locales;
617
618 AssetManager* am = assetManagerForJavaObject(env, clazz);
619 if (am == NULL) {
620 return NULL;
621 }
622
623 am->getLocales(&locales, includeSystemLocales);
624
625 const int N = locales.size();
626
627 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
628 if (result == NULL) {
629 return NULL;
630 }
631
632 for (int i=0; i<N; i++) {
633 jstring str = env->NewStringUTF(locales[i].string());
634 if (str == NULL) {
635 return NULL;
Adam Lesinski11875902017-01-23 12:58:11 -0800636 }
Adam Lesinskibde1df22018-02-09 11:12:22 -0800637 env->SetObjectArrayElement(result, i, str);
638 env->DeleteLocalRef(str);
639 }
640
641 return result;
642}
643
644static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
645{
646 return getLocales(env, clazz, true /* include system locales */);
647}
648
649static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
650{
651 return getLocales(env, clazz, false /* don't include system locales */);
652}
653
654static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
655 jobject result = env->NewObject(gConfigurationOffsets.classObject,
656 gConfigurationOffsets.constructor);
657 if (result == NULL) {
658 return NULL;
659 }
660
661 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
662 config.smallestScreenWidthDp);
663 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
664 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
665
666 return result;
667}
668
669static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
670 const Vector<ResTable_config>& configs) {
671 const int N = configs.size();
672 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
673 if (result == NULL) {
674 return NULL;
675 }
676
677 for (int i=0; i<N; i++) {
678 jobject config = constructConfigurationObject(env, configs[i]);
679 if (config == NULL) {
680 env->DeleteLocalRef(result);
681 return NULL;
682 }
683
684 env->SetObjectArrayElement(result, i, config);
685 env->DeleteLocalRef(config);
686 }
687
688 return result;
689}
690
691static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
692 AssetManager* am = assetManagerForJavaObject(env, clazz);
693 if (am == NULL) {
694 return NULL;
695 }
696
697 const ResTable& res(am->getResources());
698 Vector<ResTable_config> configs;
699 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
700
701 return getSizeConfigurationsInternal(env, configs);
702}
703
704static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
705 jint mcc, jint mnc,
706 jstring locale, jint orientation,
707 jint touchscreen, jint density,
708 jint keyboard, jint keyboardHidden,
709 jint navigation,
710 jint screenWidth, jint screenHeight,
711 jint smallestScreenWidthDp,
712 jint screenWidthDp, jint screenHeightDp,
713 jint screenLayout, jint uiMode,
714 jint colorMode, jint sdkVersion)
715{
716 AssetManager* am = assetManagerForJavaObject(env, clazz);
717 if (am == NULL) {
718 return;
719 }
720
721 ResTable_config config;
722 memset(&config, 0, sizeof(config));
723
724 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
725
726 // Constants duplicated from Java class android.content.res.Configuration.
727 static const jint kScreenLayoutRoundMask = 0x300;
728 static const jint kScreenLayoutRoundShift = 8;
729
730 config.mcc = (uint16_t)mcc;
731 config.mnc = (uint16_t)mnc;
732 config.orientation = (uint8_t)orientation;
733 config.touchscreen = (uint8_t)touchscreen;
734 config.density = (uint16_t)density;
735 config.keyboard = (uint8_t)keyboard;
736 config.inputFlags = (uint8_t)keyboardHidden;
737 config.navigation = (uint8_t)navigation;
738 config.screenWidth = (uint16_t)screenWidth;
739 config.screenHeight = (uint16_t)screenHeight;
740 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
741 config.screenWidthDp = (uint16_t)screenWidthDp;
742 config.screenHeightDp = (uint16_t)screenHeightDp;
743 config.screenLayout = (uint8_t)screenLayout;
744 config.uiMode = (uint8_t)uiMode;
745 config.colorMode = (uint8_t)colorMode;
746 config.sdkVersion = (uint16_t)sdkVersion;
747 config.minorVersion = 0;
748
749 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
750 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
751 // into screenLayout2.
752 config.screenLayout2 =
753 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
754
755 am->setConfiguration(config, locale8);
756
757 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
758}
759
760static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
761 jstring name,
762 jstring defType,
763 jstring defPackage)
764{
765 ScopedStringChars name16(env, name);
766 if (name16.get() == NULL) {
767 return 0;
768 }
769
770 AssetManager* am = assetManagerForJavaObject(env, clazz);
771 if (am == NULL) {
772 return 0;
773 }
774
775 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
776 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
777 : NULL;
778 jsize defTypeLen = defType
779 ? env->GetStringLength(defType) : 0;
780 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
781 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
782 NULL))
783 : NULL;
784 jsize defPackageLen = defPackage
785 ? env->GetStringLength(defPackage) : 0;
786
787 jint ident = am->getResources().identifierForName(
788 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
789 defType16, defTypeLen, defPackage16, defPackageLen);
790
791 if (defPackage16) {
792 env->ReleaseStringChars(defPackage,
793 reinterpret_cast<const jchar*>(defPackage16));
794 }
795 if (defType16) {
796 env->ReleaseStringChars(defType,
797 reinterpret_cast<const jchar*>(defType16));
798 }
799
800 return ident;
801}
802
803static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
804 jint resid)
805{
806 AssetManager* am = assetManagerForJavaObject(env, clazz);
807 if (am == NULL) {
808 return NULL;
809 }
810
811 ResTable::resource_name name;
812 if (!am->getResources().getResourceName(resid, true, &name)) {
813 return NULL;
814 }
815
816 String16 str;
817 if (name.package != NULL) {
818 str.setTo(name.package, name.packageLen);
819 }
820 if (name.type8 != NULL || name.type != NULL) {
821 if (str.size() > 0) {
822 char16_t div = ':';
823 str.append(&div, 1);
824 }
825 if (name.type8 != NULL) {
826 str.append(String16(name.type8, name.typeLen));
827 } else {
828 str.append(name.type, name.typeLen);
829 }
830 }
831 if (name.name8 != NULL || name.name != NULL) {
832 if (str.size() > 0) {
833 char16_t div = '/';
834 str.append(&div, 1);
835 }
836 if (name.name8 != NULL) {
837 str.append(String16(name.name8, name.nameLen));
838 } else {
839 str.append(name.name, name.nameLen);
840 }
841 }
842
843 return env->NewString((const jchar*)str.string(), str.size());
844}
845
846static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
847 jint resid)
848{
849 AssetManager* am = assetManagerForJavaObject(env, clazz);
850 if (am == NULL) {
851 return NULL;
852 }
853
854 ResTable::resource_name name;
855 if (!am->getResources().getResourceName(resid, true, &name)) {
856 return NULL;
857 }
858
859 if (name.package != NULL) {
860 return env->NewString((const jchar*)name.package, name.packageLen);
861 }
862
863 return NULL;
864}
865
866static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
867 jint resid)
868{
869 AssetManager* am = assetManagerForJavaObject(env, clazz);
870 if (am == NULL) {
871 return NULL;
872 }
873
874 ResTable::resource_name name;
875 if (!am->getResources().getResourceName(resid, true, &name)) {
876 return NULL;
877 }
878
879 if (name.type8 != NULL) {
880 return env->NewStringUTF(name.type8);
881 }
882
883 if (name.type != NULL) {
884 return env->NewString((const jchar*)name.type, name.typeLen);
885 }
886
887 return NULL;
888}
889
890static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
891 jint resid)
892{
893 AssetManager* am = assetManagerForJavaObject(env, clazz);
894 if (am == NULL) {
895 return NULL;
896 }
897
898 ResTable::resource_name name;
899 if (!am->getResources().getResourceName(resid, true, &name)) {
900 return NULL;
901 }
902
903 if (name.name8 != NULL) {
904 return env->NewStringUTF(name.name8);
905 }
906
907 if (name.name != NULL) {
908 return env->NewString((const jchar*)name.name, name.nameLen);
909 }
910
911 return NULL;
912}
913
914static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
915 jint ident,
916 jshort density,
917 jobject outValue,
918 jboolean resolve)
919{
920 if (outValue == NULL) {
921 jniThrowNullPointerException(env, "outValue");
922 return 0;
923 }
924 AssetManager* am = assetManagerForJavaObject(env, clazz);
925 if (am == NULL) {
926 return 0;
927 }
928 const ResTable& res(am->getResources());
929
930 Res_value value;
931 ResTable_config config;
932 uint32_t typeSpecFlags;
933 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
934 if (kThrowOnBadId) {
935 if (block == BAD_INDEX) {
936 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
937 return 0;
938 }
939 }
940 uint32_t ref = ident;
941 if (resolve) {
942 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
943 if (kThrowOnBadId) {
944 if (block == BAD_INDEX) {
945 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
946 return 0;
947 }
948 }
949 }
950 if (block >= 0) {
951 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
952 }
953
954 return static_cast<jint>(block);
955}
956
957static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
958 jint ident, jint bagEntryId,
959 jobject outValue, jboolean resolve)
960{
961 AssetManager* am = assetManagerForJavaObject(env, clazz);
962 if (am == NULL) {
963 return 0;
964 }
965 const ResTable& res(am->getResources());
966
967 // Now lock down the resource object and start pulling stuff from it.
968 res.lock();
969
970 ssize_t block = -1;
971 Res_value value;
972
973 const ResTable::bag_entry* entry = NULL;
974 uint32_t typeSpecFlags;
975 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
976
977 for (ssize_t i=0; i<entryCount; i++) {
978 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
979 block = entry->stringBlock;
980 value = entry->map.value;
981 }
982 entry++;
983 }
984
985 res.unlock();
986
987 if (block < 0) {
988 return static_cast<jint>(block);
989 }
990
991 uint32_t ref = ident;
992 if (resolve) {
993 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
994 if (kThrowOnBadId) {
995 if (block == BAD_INDEX) {
996 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
997 return 0;
998 }
999 }
1000 }
1001 if (block >= 0) {
1002 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
1003 }
1004
1005 return static_cast<jint>(block);
1006}
1007
1008static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
1009{
1010 AssetManager* am = assetManagerForJavaObject(env, clazz);
1011 if (am == NULL) {
1012 return 0;
1013 }
1014 return am->getResources().getTableCount();
1015}
1016
1017static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
1018 jint block)
1019{
1020 AssetManager* am = assetManagerForJavaObject(env, clazz);
1021 if (am == NULL) {
1022 return 0;
1023 }
1024 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
1025}
1026
1027static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
1028 jint cookie)
1029{
1030 AssetManager* am = assetManagerForJavaObject(env, clazz);
1031 if (am == NULL) {
1032 return NULL;
1033 }
1034 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
1035 if (name.length() == 0) {
1036 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
1037 return NULL;
1038 }
1039 jstring str = env->NewStringUTF(name.string());
1040 return str;
1041}
1042
1043static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1044{
1045 AssetManager* am = assetManagerForJavaObject(env, clazz);
1046 if (am == NULL) {
1047 return 0;
1048 }
1049
1050 const ResTable& res = am->getResources();
1051
1052 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1053 gSparseArrayOffsets.constructor);
1054 const size_t N = res.getBasePackageCount();
1055 for (size_t i = 0; i < N; i++) {
1056 const String16 name = res.getBasePackageName(i);
1057 env->CallVoidMethod(
1058 sparseArray, gSparseArrayOffsets.put,
1059 static_cast<jint>(res.getBasePackageId(i)),
1060 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1061 name.size()));
1062 }
1063 return sparseArray;
1064}
1065
1066static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
1067{
1068 AssetManager* am = assetManagerForJavaObject(env, clazz);
1069 if (am == NULL) {
1070 return 0;
1071 }
1072 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
1073}
1074
1075static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
1076 jlong themeHandle)
1077{
1078 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1079 delete theme;
1080}
1081
1082static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
1083 jlong themeHandle,
1084 jint styleRes,
1085 jboolean force)
1086{
1087 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1088 theme->applyStyle(styleRes, force ? true : false);
1089}
1090
1091static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
1092 jlong destHandle, jlong srcHandle)
1093{
1094 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1095 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
1096 dest->setTo(*src);
1097}
1098
1099static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1100{
1101 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1102 theme->clear();
1103}
1104
1105static jint android_content_AssetManager_loadThemeAttributeValue(
1106 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
1107{
1108 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1109 const ResTable& res(theme->getResTable());
1110
1111 Res_value value;
1112 // XXX value could be different in different configs!
1113 uint32_t typeSpecFlags = 0;
1114 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1115 uint32_t ref = 0;
1116 if (resolve) {
1117 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
1118 if (kThrowOnBadId) {
1119 if (block == BAD_INDEX) {
1120 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1121 return 0;
1122 }
1123 }
1124 }
1125 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1126}
1127
1128static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1129 jlong themeHandle)
1130{
1131 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1132 return theme->getChangingConfigurations();
1133}
1134
1135static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
1136 jlong themeHandle, jint pri,
1137 jstring tag, jstring prefix)
1138{
1139 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1140 const ResTable& res(theme->getResTable());
1141 (void)res;
1142
1143 // XXX Need to use params.
1144 theme->dumpToLog();
1145}
1146
1147static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1148 jlong themeToken,
1149 jint defStyleAttr,
1150 jint defStyleRes,
1151 jintArray inValues,
1152 jintArray attrs,
1153 jintArray outValues,
1154 jintArray outIndices)
1155{
1156 if (themeToken == 0) {
1157 jniThrowNullPointerException(env, "theme token");
Adam Lesinski11875902017-01-23 12:58:11 -08001158 return JNI_FALSE;
Adam Lesinski11875902017-01-23 12:58:11 -08001159 }
Adam Lesinskibde1df22018-02-09 11:12:22 -08001160 if (attrs == NULL) {
1161 jniThrowNullPointerException(env, "attrs");
Adam Lesinski11875902017-01-23 12:58:11 -08001162 return JNI_FALSE;
Adam Lesinski11875902017-01-23 12:58:11 -08001163 }
Adam Lesinskibde1df22018-02-09 11:12:22 -08001164 if (outValues == NULL) {
1165 jniThrowNullPointerException(env, "out values");
1166 return JNI_FALSE;
Adam Lesinski11875902017-01-23 12:58:11 -08001167 }
Adam Lesinskibde1df22018-02-09 11:12:22 -08001168
1169 const jsize NI = env->GetArrayLength(attrs);
1170 const jsize NV = env->GetArrayLength(outValues);
1171 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1172 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1173 return JNI_FALSE;
1174 }
1175
1176 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1177 if (src == NULL) {
1178 return JNI_FALSE;
1179 }
1180
1181 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1182 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1183
1184 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1185 if (baseDest == NULL) {
1186 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1187 return JNI_FALSE;
1188 }
1189
1190 jint* indices = NULL;
1191 if (outIndices != NULL) {
1192 if (env->GetArrayLength(outIndices) > NI) {
1193 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1194 }
1195 }
1196
1197 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1198 bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
1199 (uint32_t*) srcValues, NSV,
1200 (uint32_t*) src, NI,
1201 (uint32_t*) baseDest,
1202 (uint32_t*) indices);
1203
1204 if (indices != NULL) {
1205 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1206 }
1207 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1208 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1209 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1210 return result ? JNI_TRUE : JNI_FALSE;
Adam Lesinski11875902017-01-23 12:58:11 -08001211}
1212
Adam Lesinskibde1df22018-02-09 11:12:22 -08001213static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
1214 jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
1215 jlong outValuesAddress, jlong outIndicesAddress) {
1216 jint* attrs = env->GetIntArrayElements(attrsObj, 0);
1217 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1218 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
1219 uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
1220 uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
1221 ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
1222 reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
1223 env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
Adam Lesinski11875902017-01-23 12:58:11 -08001224}
1225
Adam Lesinskibde1df22018-02-09 11:12:22 -08001226static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
1227 jlong xmlParserToken,
1228 jintArray attrs,
1229 jintArray outValues,
1230 jintArray outIndices)
1231{
1232 if (xmlParserToken == 0) {
1233 jniThrowNullPointerException(env, "xmlParserToken");
1234 return JNI_FALSE;
1235 }
1236 if (attrs == NULL) {
1237 jniThrowNullPointerException(env, "attrs");
1238 return JNI_FALSE;
1239 }
1240 if (outValues == NULL) {
1241 jniThrowNullPointerException(env, "out values");
1242 return JNI_FALSE;
1243 }
1244
1245 AssetManager* am = assetManagerForJavaObject(env, clazz);
1246 if (am == NULL) {
1247 return JNI_FALSE;
1248 }
1249 const ResTable& res(am->getResources());
1250 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
1251
1252 const jsize NI = env->GetArrayLength(attrs);
1253 const jsize NV = env->GetArrayLength(outValues);
1254 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1255 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1256 return JNI_FALSE;
1257 }
1258
1259 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1260 if (src == NULL) {
1261 return JNI_FALSE;
1262 }
1263
1264 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1265 if (baseDest == NULL) {
1266 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1267 return JNI_FALSE;
1268 }
1269
1270 jint* indices = NULL;
1271 if (outIndices != NULL) {
1272 if (env->GetArrayLength(outIndices) > NI) {
1273 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1274 }
1275 }
1276
1277 bool result = RetrieveAttributes(&res, xmlParser,
1278 (uint32_t*) src, NI,
1279 (uint32_t*) baseDest,
1280 (uint32_t*) indices);
1281
1282 if (indices != NULL) {
1283 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1284 }
1285 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1286 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1287 return result ? JNI_TRUE : JNI_FALSE;
Adam Lesinski11875902017-01-23 12:58:11 -08001288}
1289
Adam Lesinskibde1df22018-02-09 11:12:22 -08001290static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1291 jint id)
1292{
1293 AssetManager* am = assetManagerForJavaObject(env, clazz);
1294 if (am == NULL) {
1295 return 0;
1296 }
1297 const ResTable& res(am->getResources());
1298
1299 res.lock();
1300 const ResTable::bag_entry* defStyleEnt = NULL;
1301 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1302 res.unlock();
1303
1304 return static_cast<jint>(bagOff);
Adam Lesinski11875902017-01-23 12:58:11 -08001305}
1306
Adam Lesinskibde1df22018-02-09 11:12:22 -08001307static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1308 jint id,
1309 jintArray outValues)
1310{
1311 if (outValues == NULL) {
1312 jniThrowNullPointerException(env, "out values");
1313 return JNI_FALSE;
1314 }
1315
1316 AssetManager* am = assetManagerForJavaObject(env, clazz);
1317 if (am == NULL) {
1318 return JNI_FALSE;
1319 }
1320 const ResTable& res(am->getResources());
1321 ResTable_config config;
1322 Res_value value;
1323 ssize_t block;
1324
1325 const jsize NV = env->GetArrayLength(outValues);
1326
1327 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1328 jint* dest = baseDest;
1329 if (dest == NULL) {
1330 jniThrowException(env, "java/lang/OutOfMemoryError", "");
1331 return JNI_FALSE;
1332 }
1333
1334 // Now lock down the resource object and start pulling stuff from it.
1335 res.lock();
1336
1337 const ResTable::bag_entry* arrayEnt = NULL;
1338 uint32_t arrayTypeSetFlags = 0;
1339 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1340 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1341 (bagOff >= 0 ? bagOff : 0);
1342
1343 int i = 0;
1344 uint32_t typeSetFlags;
1345 while (i < NV && arrayEnt < endArrayEnt) {
1346 block = arrayEnt->stringBlock;
1347 typeSetFlags = arrayTypeSetFlags;
1348 config.density = 0;
1349 value = arrayEnt->map.value;
1350
1351 uint32_t resid = 0;
1352 if (value.dataType != Res_value::TYPE_NULL) {
1353 // Take care of resolving the found resource to its final value.
1354 //printf("Resolving attribute reference\n");
1355 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1356 &typeSetFlags, &config);
1357 if (kThrowOnBadId) {
1358 if (newBlock == BAD_INDEX) {
1359 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1360 return JNI_FALSE;
1361 }
1362 }
1363 if (newBlock >= 0) block = newBlock;
1364 }
1365
1366 // Deal with the special @null value -- it turns back to TYPE_NULL.
1367 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1368 value.dataType = Res_value::TYPE_NULL;
1369 value.data = Res_value::DATA_NULL_UNDEFINED;
1370 }
1371
1372 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1373
1374 // Write the final value back to Java.
1375 dest[STYLE_TYPE] = value.dataType;
1376 dest[STYLE_DATA] = value.data;
1377 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
1378 dest[STYLE_RESOURCE_ID] = resid;
1379 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1380 dest[STYLE_DENSITY] = config.density;
1381 dest += STYLE_NUM_ENTRIES;
1382 i+= STYLE_NUM_ENTRIES;
1383 arrayEnt++;
1384 }
1385
1386 i /= STYLE_NUM_ENTRIES;
1387
1388 res.unlock();
1389
1390 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1391
1392 return i;
Adam Lesinski11875902017-01-23 12:58:11 -08001393}
1394
Adam Lesinskibde1df22018-02-09 11:12:22 -08001395static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
1396 jint cookie,
1397 jstring fileName)
1398{
1399 AssetManager* am = assetManagerForJavaObject(env, clazz);
1400 if (am == NULL) {
1401 return 0;
1402 }
Adam Lesinski11875902017-01-23 12:58:11 -08001403
Adam Lesinskibde1df22018-02-09 11:12:22 -08001404 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
Adam Lesinski11875902017-01-23 12:58:11 -08001405
Adam Lesinskibde1df22018-02-09 11:12:22 -08001406 ScopedUtfChars fileName8(env, fileName);
1407 if (fileName8.c_str() == NULL) {
1408 return 0;
1409 }
Adam Lesinski11875902017-01-23 12:58:11 -08001410
Adam Lesinskibde1df22018-02-09 11:12:22 -08001411 int32_t assetCookie = static_cast<int32_t>(cookie);
1412 Asset* a = assetCookie
1413 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1414 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
1415
1416 if (a == NULL) {
1417 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
1418 return 0;
1419 }
1420
1421 const DynamicRefTable* dynamicRefTable =
1422 am->getResources().getDynamicRefTableForCookie(assetCookie);
1423 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
1424 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1425 a->close();
1426 delete a;
1427
1428 if (err != NO_ERROR) {
1429 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
1430 return 0;
1431 }
1432
1433 return reinterpret_cast<jlong>(block);
Adam Lesinski11875902017-01-23 12:58:11 -08001434}
1435
Adam Lesinskibde1df22018-02-09 11:12:22 -08001436static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1437 jint arrayResId)
1438{
1439 AssetManager* am = assetManagerForJavaObject(env, clazz);
1440 if (am == NULL) {
1441 return NULL;
1442 }
1443 const ResTable& res(am->getResources());
1444
1445 const ResTable::bag_entry* startOfBag;
1446 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1447 if (N < 0) {
1448 return NULL;
1449 }
1450
1451 jintArray array = env->NewIntArray(N * 2);
1452 if (array == NULL) {
1453 res.unlockBag(startOfBag);
1454 return NULL;
1455 }
1456
1457 Res_value value;
1458 const ResTable::bag_entry* bag = startOfBag;
1459 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1460 jint stringIndex = -1;
1461 jint stringBlock = 0;
1462 value = bag->map.value;
1463
1464 // Take care of resolving the found resource to its final value.
1465 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1466 if (value.dataType == Res_value::TYPE_STRING) {
1467 stringIndex = value.data;
1468 }
1469
1470 if (kThrowOnBadId) {
1471 if (stringBlock == BAD_INDEX) {
1472 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1473 return array;
1474 }
1475 }
1476
1477 //todo: It might be faster to allocate a C array to contain
1478 // the blocknums and indices, put them in there and then
1479 // do just one SetIntArrayRegion()
1480 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1481 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1482 j = j + 2;
1483 }
1484 res.unlockBag(startOfBag);
1485 return array;
Adam Lesinski11875902017-01-23 12:58:11 -08001486}
1487
Adam Lesinskibde1df22018-02-09 11:12:22 -08001488static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1489 jint arrayResId)
1490{
1491 AssetManager* am = assetManagerForJavaObject(env, clazz);
1492 if (am == NULL) {
1493 return NULL;
1494 }
1495 const ResTable& res(am->getResources());
1496
1497 const ResTable::bag_entry* startOfBag;
1498 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1499 if (N < 0) {
1500 return NULL;
1501 }
1502
1503 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
1504 if (env->ExceptionCheck()) {
1505 res.unlockBag(startOfBag);
1506 return NULL;
1507 }
1508
1509 Res_value value;
1510 const ResTable::bag_entry* bag = startOfBag;
1511 size_t strLen = 0;
1512 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1513 value = bag->map.value;
1514 jstring str = NULL;
1515
1516 // Take care of resolving the found resource to its final value.
1517 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
1518 if (kThrowOnBadId) {
1519 if (block == BAD_INDEX) {
1520 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1521 return array;
1522 }
1523 }
1524 if (value.dataType == Res_value::TYPE_STRING) {
1525 const ResStringPool* pool = res.getTableStringBlock(block);
1526 const char* str8 = pool->string8At(value.data, &strLen);
1527 if (str8 != NULL) {
1528 str = env->NewStringUTF(str8);
1529 } else {
1530 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1531 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1532 strLen);
1533 }
1534
1535 // If one of our NewString{UTF} calls failed due to memory, an
1536 // exception will be pending.
1537 if (env->ExceptionCheck()) {
1538 res.unlockBag(startOfBag);
1539 return NULL;
1540 }
1541
1542 env->SetObjectArrayElement(array, i, str);
1543
1544 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1545 // If we have a large amount of strings in our array, we might
1546 // overflow the local reference table of the VM.
1547 env->DeleteLocalRef(str);
1548 }
1549 }
1550 res.unlockBag(startOfBag);
1551 return array;
Adam Lesinski11875902017-01-23 12:58:11 -08001552}
1553
Adam Lesinskibde1df22018-02-09 11:12:22 -08001554static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1555 jint arrayResId)
1556{
1557 AssetManager* am = assetManagerForJavaObject(env, clazz);
1558 if (am == NULL) {
1559 return NULL;
1560 }
1561 const ResTable& res(am->getResources());
1562
1563 const ResTable::bag_entry* startOfBag;
1564 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1565 if (N < 0) {
1566 return NULL;
1567 }
1568
1569 jintArray array = env->NewIntArray(N);
1570 if (array == NULL) {
1571 res.unlockBag(startOfBag);
1572 return NULL;
1573 }
1574
1575 Res_value value;
1576 const ResTable::bag_entry* bag = startOfBag;
1577 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1578 value = bag->map.value;
1579
1580 // Take care of resolving the found resource to its final value.
1581 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
1582 if (kThrowOnBadId) {
1583 if (block == BAD_INDEX) {
1584 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1585 return array;
1586 }
1587 }
1588 if (value.dataType >= Res_value::TYPE_FIRST_INT
1589 && value.dataType <= Res_value::TYPE_LAST_INT) {
1590 int intVal = value.data;
1591 env->SetIntArrayRegion(array, i, 1, &intVal);
1592 }
1593 }
1594 res.unlockBag(startOfBag);
1595 return array;
1596}
1597
1598static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1599 jint styleId)
1600{
1601 AssetManager* am = assetManagerForJavaObject(env, clazz);
1602 if (am == NULL) {
1603 return NULL;
1604 }
1605 const ResTable& res(am->getResources());
1606
1607 const ResTable::bag_entry* startOfBag;
1608 const ssize_t N = res.lockBag(styleId, &startOfBag);
1609 if (N < 0) {
1610 return NULL;
1611 }
1612
1613 jintArray array = env->NewIntArray(N);
1614 if (array == NULL) {
1615 res.unlockBag(startOfBag);
1616 return NULL;
1617 }
1618
1619 const ResTable::bag_entry* bag = startOfBag;
1620 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1621 int resourceId = bag->map.name.ident;
1622 env->SetIntArrayRegion(array, i, 1, &resourceId);
1623 }
1624 res.unlockBag(startOfBag);
1625 return array;
1626}
1627
1628static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
1629{
1630 if (isSystem) {
1631 verifySystemIdmaps();
1632 }
1633 AssetManager* am = new AssetManager();
1634 if (am == NULL) {
1635 jniThrowException(env, "java/lang/OutOfMemoryError", "");
1636 return;
1637 }
1638
1639 am->addDefaultAssets();
1640
1641 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
1642 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
1643}
1644
1645static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1646{
1647 AssetManager* am = (AssetManager*)
1648 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
1649 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
1650 if (am != NULL) {
1651 delete am;
1652 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
1653 }
1654}
1655
1656static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1657{
1658 return Asset::getGlobalCount();
1659}
1660
1661static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1662{
1663 String8 alloc = Asset::getAssetAllocations();
1664 if (alloc.length() <= 0) {
1665 return NULL;
1666 }
1667
1668 jstring str = env->NewStringUTF(alloc.string());
1669 return str;
1670}
1671
1672static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1673{
1674 return AssetManager::getGlobalCount();
Adam Lesinski11875902017-01-23 12:58:11 -08001675}
1676
1677// ----------------------------------------------------------------------------
1678
Adam Lesinskibde1df22018-02-09 11:12:22 -08001679/*
1680 * JNI registration.
1681 */
Adam Lesinski11875902017-01-23 12:58:11 -08001682static const JNINativeMethod gAssetManagerMethods[] = {
Adam Lesinskibde1df22018-02-09 11:12:22 -08001683 /* name, signature, funcPtr */
Adam Lesinski11875902017-01-23 12:58:11 -08001684
Adam Lesinskibde1df22018-02-09 11:12:22 -08001685 // Basic asset stuff.
1686 { "openAsset", "(Ljava/lang/String;I)J",
1687 (void*) android_content_AssetManager_openAsset },
1688 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1689 (void*) android_content_AssetManager_openAssetFd },
1690 { "openNonAssetNative", "(ILjava/lang/String;I)J",
1691 (void*) android_content_AssetManager_openNonAssetNative },
1692 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1693 (void*) android_content_AssetManager_openNonAssetFdNative },
1694 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1695 (void*) android_content_AssetManager_list },
1696 { "destroyAsset", "(J)V",
1697 (void*) android_content_AssetManager_destroyAsset },
1698 { "readAssetChar", "(J)I",
1699 (void*) android_content_AssetManager_readAssetChar },
1700 { "readAsset", "(J[BII)I",
1701 (void*) android_content_AssetManager_readAsset },
1702 { "seekAsset", "(JJI)J",
1703 (void*) android_content_AssetManager_seekAsset },
1704 { "getAssetLength", "(J)J",
1705 (void*) android_content_AssetManager_getAssetLength },
1706 { "getAssetRemainingLength", "(J)J",
1707 (void*) android_content_AssetManager_getAssetRemainingLength },
1708 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
1709 (void*) android_content_AssetManager_addAssetPath },
1710 { "addAssetFdNative", "(Ljava/io/FileDescriptor;Ljava/lang/String;Z)I",
1711 (void*) android_content_AssetManager_addAssetFd },
1712 { "addOverlayPathNative", "(Ljava/lang/String;)I",
1713 (void*) android_content_AssetManager_addOverlayPath },
1714 { "isUpToDate", "()Z",
1715 (void*) android_content_AssetManager_isUpToDate },
Adam Lesinski11875902017-01-23 12:58:11 -08001716
Adam Lesinskibde1df22018-02-09 11:12:22 -08001717 // Resources.
1718 { "getLocales", "()[Ljava/lang/String;",
1719 (void*) android_content_AssetManager_getLocales },
1720 { "getNonSystemLocales", "()[Ljava/lang/String;",
1721 (void*) android_content_AssetManager_getNonSystemLocales },
1722 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
1723 (void*) android_content_AssetManager_getSizeConfigurations },
1724 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
1725 (void*) android_content_AssetManager_setConfiguration },
1726 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
1727 (void*) android_content_AssetManager_getResourceIdentifier },
1728 { "getResourceName","(I)Ljava/lang/String;",
1729 (void*) android_content_AssetManager_getResourceName },
1730 { "getResourcePackageName","(I)Ljava/lang/String;",
1731 (void*) android_content_AssetManager_getResourcePackageName },
1732 { "getResourceTypeName","(I)Ljava/lang/String;",
1733 (void*) android_content_AssetManager_getResourceTypeName },
1734 { "getResourceEntryName","(I)Ljava/lang/String;",
1735 (void*) android_content_AssetManager_getResourceEntryName },
1736 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
1737 (void*) android_content_AssetManager_loadResourceValue },
1738 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
1739 (void*) android_content_AssetManager_loadResourceBagValue },
1740 { "getStringBlockCount","()I",
1741 (void*) android_content_AssetManager_getStringBlockCount },
1742 { "getNativeStringBlock","(I)J",
1743 (void*) android_content_AssetManager_getNativeStringBlock },
1744 { "getCookieName","(I)Ljava/lang/String;",
1745 (void*) android_content_AssetManager_getCookieName },
1746 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
1747 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
Adam Lesinski11875902017-01-23 12:58:11 -08001748
Adam Lesinskibde1df22018-02-09 11:12:22 -08001749 // Themes.
1750 { "newTheme", "()J",
1751 (void*) android_content_AssetManager_newTheme },
1752 { "deleteTheme", "(J)V",
1753 (void*) android_content_AssetManager_deleteTheme },
1754 { "applyThemeStyle", "(JIZ)V",
1755 (void*) android_content_AssetManager_applyThemeStyle },
1756 { "copyTheme", "(JJ)V",
1757 (void*) android_content_AssetManager_copyTheme },
1758 { "clearTheme", "(J)V",
1759 (void*) android_content_AssetManager_clearTheme },
1760 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
1761 (void*) android_content_AssetManager_loadThemeAttributeValue },
1762 { "getThemeChangingConfigurations", "(J)I",
1763 (void*) android_content_AssetManager_getThemeChangingConfigurations },
1764 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
1765 (void*) android_content_AssetManager_dumpTheme },
1766 { "applyStyle","(JIIJ[IIJJ)V",
1767 (void*) android_content_AssetManager_applyStyle },
1768 { "resolveAttrs","(JII[I[I[I[I)Z",
1769 (void*) android_content_AssetManager_resolveAttrs },
1770 { "retrieveAttributes","(J[I[I[I)Z",
1771 (void*) android_content_AssetManager_retrieveAttributes },
1772 { "getArraySize","(I)I",
1773 (void*) android_content_AssetManager_getArraySize },
1774 { "retrieveArray","(I[I)I",
1775 (void*) android_content_AssetManager_retrieveArray },
Adam Lesinski11875902017-01-23 12:58:11 -08001776
Adam Lesinskibde1df22018-02-09 11:12:22 -08001777 // XML files.
1778 { "openXmlAssetNative", "(ILjava/lang/String;)J",
1779 (void*) android_content_AssetManager_openXmlAssetNative },
Adam Lesinski11875902017-01-23 12:58:11 -08001780
Adam Lesinskibde1df22018-02-09 11:12:22 -08001781 // Arrays.
1782 { "getArrayStringResource","(I)[Ljava/lang/String;",
1783 (void*) android_content_AssetManager_getArrayStringResource },
1784 { "getArrayStringInfo","(I)[I",
1785 (void*) android_content_AssetManager_getArrayStringInfo },
1786 { "getArrayIntResource","(I)[I",
1787 (void*) android_content_AssetManager_getArrayIntResource },
1788 { "getStyleAttributes","(I)[I",
1789 (void*) android_content_AssetManager_getStyleAttributes },
Adam Lesinski11875902017-01-23 12:58:11 -08001790
Adam Lesinskibde1df22018-02-09 11:12:22 -08001791 // Bookkeeping.
1792 { "init", "(Z)V",
1793 (void*) android_content_AssetManager_init },
1794 { "destroy", "()V",
1795 (void*) android_content_AssetManager_destroy },
1796 { "getGlobalAssetCount", "()I",
1797 (void*) android_content_AssetManager_getGlobalAssetCount },
1798 { "getAssetAllocations", "()Ljava/lang/String;",
1799 (void*) android_content_AssetManager_getAssetAllocations },
1800 { "getGlobalAssetManagerCount", "()I",
1801 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
Adam Lesinski11875902017-01-23 12:58:11 -08001802};
1803
Adam Lesinskibde1df22018-02-09 11:12:22 -08001804int register_android_content_AssetManager(JNIEnv* env)
1805{
1806 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
1807 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
1808 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
1809 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
1810 "Ljava/lang/CharSequence;");
1811 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
1812 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
1813 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
1814 "changingConfigurations", "I");
1815 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
Adam Lesinski11875902017-01-23 12:58:11 -08001816
Adam Lesinskibde1df22018-02-09 11:12:22 -08001817 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
1818 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
1819 "Landroid/os/ParcelFileDescriptor;");
1820 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
1821 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
Adam Lesinski11875902017-01-23 12:58:11 -08001822
Adam Lesinskibde1df22018-02-09 11:12:22 -08001823 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
1824 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
Adam Lesinski11875902017-01-23 12:58:11 -08001825
Adam Lesinskibde1df22018-02-09 11:12:22 -08001826 jclass stringClass = FindClassOrDie(env, "java/lang/String");
1827 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
Adam Lesinski11875902017-01-23 12:58:11 -08001828
Adam Lesinskibde1df22018-02-09 11:12:22 -08001829 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
1830 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
1831 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
1832 "<init>", "()V");
1833 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
1834 "(ILjava/lang/Object;)V");
Adam Lesinski11875902017-01-23 12:58:11 -08001835
Adam Lesinskibde1df22018-02-09 11:12:22 -08001836 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
1837 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
1838 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
1839 "<init>", "()V");
1840 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
1841 "smallestScreenWidthDp", "I");
1842 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
1843 "screenWidthDp", "I");
1844 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
1845 "screenHeightDp", "I");
Adam Lesinski11875902017-01-23 12:58:11 -08001846
Adam Lesinskibde1df22018-02-09 11:12:22 -08001847 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
1848 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849}
1850
1851}; // namespace android