android_os_Parcel.cpp revision 047238ced42eea812de9d39a9f32e94d002bfa5c
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "Parcel" 18//#define LOG_NDEBUG 0 19 20#include "android_os_Parcel.h" 21#include "android_util_Binder.h" 22 23#include "JNIHelp.h" 24 25#include <fcntl.h> 26#include <stdio.h> 27#include <sys/stat.h> 28#include <sys/types.h> 29#include <unistd.h> 30 31#include <utils/Atomic.h> 32#include <binder/IInterface.h> 33#include <binder/IPCThreadState.h> 34#include <utils/Log.h> 35#include <utils/SystemClock.h> 36#include <utils/List.h> 37#include <utils/KeyedVector.h> 38#include <cutils/logger.h> 39#include <binder/Parcel.h> 40#include <binder/ProcessState.h> 41#include <binder/IServiceManager.h> 42#include <utils/threads.h> 43#include <utils/String8.h> 44 45#include <ScopedUtfChars.h> 46#include <ScopedLocalRef.h> 47 48#include <android_runtime/AndroidRuntime.h> 49 50//#undef ALOGV 51//#define ALOGV(...) fprintf(stderr, __VA_ARGS__) 52 53#define DEBUG_DEATH 0 54#if DEBUG_DEATH 55#define LOGDEATH ALOGD 56#else 57#define LOGDEATH ALOGV 58#endif 59 60namespace android { 61 62static struct parcel_offsets_t 63{ 64 jfieldID mNativePtr; 65} gParcelOffsets; 66 67Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) 68{ 69 if (obj) { 70 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mNativePtr); 71 if (p != NULL) { 72 return p; 73 } 74 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!"); 75 } 76 return NULL; 77} 78 79static jint android_os_Parcel_dataSize(JNIEnv* env, jclass clazz, jint nativePtr) 80{ 81 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 82 return parcel ? parcel->dataSize() : 0; 83} 84 85static jint android_os_Parcel_dataAvail(JNIEnv* env, jclass clazz, jint nativePtr) 86{ 87 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 88 return parcel ? parcel->dataAvail() : 0; 89} 90 91static jint android_os_Parcel_dataPosition(JNIEnv* env, jclass clazz, jint nativePtr) 92{ 93 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 94 return parcel ? parcel->dataPosition() : 0; 95} 96 97static jint android_os_Parcel_dataCapacity(JNIEnv* env, jclass clazz, jint nativePtr) 98{ 99 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 100 return parcel ? parcel->dataCapacity() : 0; 101} 102 103static void android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jint nativePtr, jint size) 104{ 105 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 106 if (parcel != NULL) { 107 const status_t err = parcel->setDataSize(size); 108 if (err != NO_ERROR) { 109 signalExceptionForError(env, clazz, err); 110 } 111 } 112} 113 114static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jint nativePtr, jint pos) 115{ 116 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 117 if (parcel != NULL) { 118 parcel->setDataPosition(pos); 119 } 120} 121 122static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jint nativePtr, jint size) 123{ 124 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 125 if (parcel != NULL) { 126 const status_t err = parcel->setDataCapacity(size); 127 if (err != NO_ERROR) { 128 signalExceptionForError(env, clazz, err); 129 } 130 } 131} 132 133static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean allowFds) 134{ 135 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 136 jboolean ret = JNI_TRUE; 137 if (parcel != NULL) { 138 ret = (jboolean)parcel->pushAllowFds(allowFds); 139 } 140 return ret; 141} 142 143static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean lastValue) 144{ 145 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 146 if (parcel != NULL) { 147 parcel->restoreAllowFds((bool)lastValue); 148 } 149} 150 151static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jint nativePtr, jobject data, 152 jint offset, jint length) 153{ 154 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 155 if (parcel == NULL) { 156 return; 157 } 158 159 const status_t err = parcel->writeInt32(length); 160 if (err != NO_ERROR) { 161 signalExceptionForError(env, clazz, err); 162 return; 163 } 164 165 void* dest = parcel->writeInplace(length); 166 if (dest == NULL) { 167 signalExceptionForError(env, clazz, NO_MEMORY); 168 return; 169 } 170 171 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 172 if (ar) { 173 memcpy(dest, ar + offset, length); 174 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 175 } 176} 177 178static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jint nativePtr, jint val) { 179 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 180 const status_t err = parcel->writeInt32(val); 181 if (err != NO_ERROR) { 182 signalExceptionForError(env, clazz, err); 183 } 184} 185 186static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jint nativePtr, jlong val) 187{ 188 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 189 if (parcel != NULL) { 190 const status_t err = parcel->writeInt64(val); 191 if (err != NO_ERROR) { 192 signalExceptionForError(env, clazz, err); 193 } 194 } 195} 196 197static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jint nativePtr, jfloat val) 198{ 199 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 200 if (parcel != NULL) { 201 const status_t err = parcel->writeFloat(val); 202 if (err != NO_ERROR) { 203 signalExceptionForError(env, clazz, err); 204 } 205 } 206} 207 208static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jint nativePtr, jdouble val) 209{ 210 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 211 if (parcel != NULL) { 212 const status_t err = parcel->writeDouble(val); 213 if (err != NO_ERROR) { 214 signalExceptionForError(env, clazz, err); 215 } 216 } 217} 218 219static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jint nativePtr, jstring val) 220{ 221 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 222 if (parcel != NULL) { 223 status_t err = NO_MEMORY; 224 if (val) { 225 const jchar* str = env->GetStringCritical(val, 0); 226 if (str) { 227 err = parcel->writeString16(str, env->GetStringLength(val)); 228 env->ReleaseStringCritical(val, str); 229 } 230 } else { 231 err = parcel->writeString16(NULL, 0); 232 } 233 if (err != NO_ERROR) { 234 signalExceptionForError(env, clazz, err); 235 } 236 } 237} 238 239static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object) 240{ 241 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 242 if (parcel != NULL) { 243 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 244 if (err != NO_ERROR) { 245 signalExceptionForError(env, clazz, err); 246 } 247 } 248} 249 250static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr, jobject object) 251{ 252 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 253 if (parcel != NULL) { 254 const status_t err = 255 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object)); 256 if (err != NO_ERROR) { 257 signalExceptionForError(env, clazz, err); 258 } 259 } 260} 261 262static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jint nativePtr) 263{ 264 jbyteArray ret = NULL; 265 266 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 267 if (parcel != NULL) { 268 int32_t len = parcel->readInt32(); 269 270 // sanity check the stored length against the true data size 271 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 272 ret = env->NewByteArray(len); 273 274 if (ret != NULL) { 275 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 276 if (a2) { 277 const void* data = parcel->readInplace(len); 278 memcpy(a2, data, len); 279 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 280 } 281 } 282 } 283 } 284 285 return ret; 286} 287 288static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jint nativePtr) 289{ 290 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 291 if (parcel != NULL) { 292 return parcel->readInt32(); 293 } 294 return 0; 295} 296 297static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jint nativePtr) 298{ 299 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 300 if (parcel != NULL) { 301 return parcel->readInt64(); 302 } 303 return 0; 304} 305 306static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jint nativePtr) 307{ 308 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 309 if (parcel != NULL) { 310 return parcel->readFloat(); 311 } 312 return 0; 313} 314 315static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jint nativePtr) 316{ 317 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 318 if (parcel != NULL) { 319 return parcel->readDouble(); 320 } 321 return 0; 322} 323 324static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jint nativePtr) 325{ 326 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 327 if (parcel != NULL) { 328 size_t len; 329 const char16_t* str = parcel->readString16Inplace(&len); 330 if (str) { 331 return env->NewString(str, len); 332 } 333 return NULL; 334 } 335 return NULL; 336} 337 338static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr) 339{ 340 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 341 if (parcel != NULL) { 342 return javaObjectForIBinder(env, parcel->readStrongBinder()); 343 } 344 return NULL; 345} 346 347static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr) 348{ 349 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 350 if (parcel != NULL) { 351 int fd = parcel->readFileDescriptor(); 352 if (fd < 0) return NULL; 353 fd = dup(fd); 354 if (fd < 0) return NULL; 355 return jniCreateFileDescriptor(env, fd); 356 } 357 return NULL; 358} 359 360static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz, 361 jstring name, jint mode) 362{ 363 if (name == NULL) { 364 jniThrowNullPointerException(env, NULL); 365 return NULL; 366 } 367 const jchar* str = env->GetStringCritical(name, 0); 368 if (str == NULL) { 369 // Whatever, whatever. 370 jniThrowException(env, "java/lang/IllegalStateException", NULL); 371 return NULL; 372 } 373 String8 name8(str, env->GetStringLength(name)); 374 env->ReleaseStringCritical(name, str); 375 int flags=0; 376 switch (mode&0x30000000) { 377 case 0: 378 case 0x10000000: 379 flags = O_RDONLY; 380 break; 381 case 0x20000000: 382 flags = O_WRONLY; 383 break; 384 case 0x30000000: 385 flags = O_RDWR; 386 break; 387 } 388 389 if (mode&0x08000000) flags |= O_CREAT; 390 if (mode&0x04000000) flags |= O_TRUNC; 391 if (mode&0x02000000) flags |= O_APPEND; 392 393 int realMode = S_IRWXU|S_IRWXG; 394 if (mode&0x00000001) realMode |= S_IROTH; 395 if (mode&0x00000002) realMode |= S_IWOTH; 396 397 int fd = open(name8.string(), flags, realMode); 398 if (fd < 0) { 399 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno)); 400 return NULL; 401 } 402 jobject object = jniCreateFileDescriptor(env, fd); 403 if (object == NULL) { 404 close(fd); 405 } 406 return object; 407} 408 409static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig) 410{ 411 if (orig == NULL) { 412 jniThrowNullPointerException(env, NULL); 413 return NULL; 414 } 415 int origfd = jniGetFDFromFileDescriptor(env, orig); 416 if (origfd < 0) { 417 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor"); 418 return NULL; 419 } 420 421 int fd = dup(origfd); 422 if (fd < 0) { 423 jniThrowIOException(env, errno); 424 return NULL; 425 } 426 jobject object = jniCreateFileDescriptor(env, fd); 427 if (object == NULL) { 428 close(fd); 429 } 430 return object; 431} 432 433static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object) 434{ 435 if (object == NULL) { 436 jniThrowNullPointerException(env, NULL); 437 return; 438 } 439 int fd = jniGetFDFromFileDescriptor(env, object); 440 if (fd >= 0) { 441 jniSetFileDescriptorOfFD(env, object, -1); 442 //ALOGI("Closing ParcelFileDescriptor %d\n", fd); 443 close(fd); 444 } 445} 446 447static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object) 448{ 449 if (object == NULL) { 450 jniThrowNullPointerException(env, NULL); 451 return; 452 } 453 int fd = jniGetFDFromFileDescriptor(env, object); 454 if (fd >= 0) { 455 jniSetFileDescriptorOfFD(env, object, -1); 456 } 457} 458 459static jint android_os_Parcel_create(JNIEnv* env, jclass clazz) 460{ 461 Parcel* parcel = new Parcel(); 462 return reinterpret_cast<jint>(parcel); 463} 464 465static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jint nativePtr) 466{ 467 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 468 if (parcel != NULL) { 469 parcel->freeData(); 470 } 471} 472 473static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jint nativePtr) 474{ 475 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 476 delete parcel; 477} 478 479static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jint nativePtr) 480{ 481 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 482 if (parcel == NULL) { 483 return NULL; 484 } 485 486 // do not marshall if there are binder objects in the parcel 487 if (parcel->objectsCount()) 488 { 489 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 490 return NULL; 491 } 492 493 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 494 495 if (ret != NULL) 496 { 497 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 498 if (array != NULL) 499 { 500 memcpy(array, parcel->data(), parcel->dataSize()); 501 env->ReleasePrimitiveArrayCritical(ret, array, 0); 502 } 503 } 504 505 return ret; 506} 507 508static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jint nativePtr, 509 jbyteArray data, jint offset, jint length) 510{ 511 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 512 if (parcel == NULL || length < 0) { 513 return; 514 } 515 516 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 517 if (array) 518 { 519 parcel->setDataSize(length); 520 parcel->setDataPosition(0); 521 522 void* raw = parcel->writeInplace(length); 523 memcpy(raw, (array + offset), length); 524 525 env->ReleasePrimitiveArrayCritical(data, array, 0); 526 } 527} 528 529static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jint thisNativePtr, 530 jint otherNativePtr, jint offset, jint length) 531{ 532 Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr); 533 if (thisParcel == NULL) { 534 return; 535 } 536 Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr); 537 if (otherParcel == NULL) { 538 return; 539 } 540 541 status_t err = thisParcel->appendFrom(otherParcel, offset, length); 542 if (err != NO_ERROR) { 543 signalExceptionForError(env, clazz, err); 544 } 545} 546 547static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jint nativePtr) 548{ 549 jboolean ret = JNI_FALSE; 550 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 551 if (parcel != NULL) { 552 if (parcel->hasFileDescriptors()) { 553 ret = JNI_TRUE; 554 } 555 } 556 return ret; 557} 558 559static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr, 560 jstring name) 561{ 562 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 563 if (parcel != NULL) { 564 // In the current implementation, the token is just the serialized interface name that 565 // the caller expects to be invoking 566 const jchar* str = env->GetStringCritical(name, 0); 567 if (str != NULL) { 568 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 569 env->ReleaseStringCritical(name, str); 570 } 571 } 572} 573 574static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jint nativePtr, jstring name) 575{ 576 jboolean ret = JNI_FALSE; 577 578 Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr); 579 if (parcel != NULL) { 580 const jchar* str = env->GetStringCritical(name, 0); 581 if (str) { 582 IPCThreadState* threadState = IPCThreadState::self(); 583 const int32_t oldPolicy = threadState->getStrictModePolicy(); 584 const bool isValid = parcel->enforceInterface( 585 String16(str, env->GetStringLength(name)), 586 threadState); 587 env->ReleaseStringCritical(name, str); 588 if (isValid) { 589 const int32_t newPolicy = threadState->getStrictModePolicy(); 590 if (oldPolicy != newPolicy) { 591 // Need to keep the Java-level thread-local strict 592 // mode policy in sync for the libcore 593 // enforcements, which involves an upcall back 594 // into Java. (We can't modify the 595 // Parcel.enforceInterface signature, as it's 596 // pseudo-public, and used via AIDL 597 // auto-generation...) 598 set_dalvik_blockguard_policy(env, newPolicy); 599 } 600 return; // everything was correct -> return silently 601 } 602 } 603 } 604 605 // all error conditions wind up here 606 jniThrowException(env, "java/lang/SecurityException", 607 "Binder invocation to an incorrect interface"); 608} 609 610// ---------------------------------------------------------------------------- 611 612static const JNINativeMethod gParcelMethods[] = { 613 {"nativeDataSize", "(I)I", (void*)android_os_Parcel_dataSize}, 614 {"nativeDataAvail", "(I)I", (void*)android_os_Parcel_dataAvail}, 615 {"nativeDataPosition", "(I)I", (void*)android_os_Parcel_dataPosition}, 616 {"nativeDataCapacity", "(I)I", (void*)android_os_Parcel_dataCapacity}, 617 {"nativeSetDataSize", "(II)V", (void*)android_os_Parcel_setDataSize}, 618 {"nativeSetDataPosition", "(II)V", (void*)android_os_Parcel_setDataPosition}, 619 {"nativeSetDataCapacity", "(II)V", (void*)android_os_Parcel_setDataCapacity}, 620 621 {"nativePushAllowFds", "(IZ)Z", (void*)android_os_Parcel_pushAllowFds}, 622 {"nativeRestoreAllowFds", "(IZ)V", (void*)android_os_Parcel_restoreAllowFds}, 623 624 {"nativeWriteByteArray", "(I[BII)V", (void*)android_os_Parcel_writeNative}, 625 {"nativeWriteInt", "(II)V", (void*)android_os_Parcel_writeInt}, 626 {"nativeWriteLong", "(IJ)V", (void*)android_os_Parcel_writeLong}, 627 {"nativeWriteFloat", "(IF)V", (void*)android_os_Parcel_writeFloat}, 628 {"nativeWriteDouble", "(ID)V", (void*)android_os_Parcel_writeDouble}, 629 {"nativeWriteString", "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeString}, 630 {"nativeWriteStrongBinder", "(ILandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 631 {"nativeWriteFileDescriptor", "(ILjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 632 633 {"nativeCreateByteArray", "(I)[B", (void*)android_os_Parcel_createByteArray}, 634 {"nativeReadInt", "(I)I", (void*)android_os_Parcel_readInt}, 635 {"nativeReadLong", "(I)J", (void*)android_os_Parcel_readLong}, 636 {"nativeReadFloat", "(I)F", (void*)android_os_Parcel_readFloat}, 637 {"nativeReadDouble", "(I)D", (void*)android_os_Parcel_readDouble}, 638 {"nativeReadString", "(I)Ljava/lang/String;", (void*)android_os_Parcel_readString}, 639 {"nativeReadStrongBinder", "(I)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 640 {"nativeReadFileDescriptor", "(I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 641 642 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 643 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor}, 644 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 645 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor}, 646 647 {"nativeCreate", "()I", (void*)android_os_Parcel_create}, 648 {"nativeFreeBuffer", "(I)V", (void*)android_os_Parcel_freeBuffer}, 649 {"nativeDestroy", "(I)V", (void*)android_os_Parcel_destroy}, 650 651 {"nativeMarshall", "(I)[B", (void*)android_os_Parcel_marshall}, 652 {"nativeUnmarshall", "(I[BII)V", (void*)android_os_Parcel_unmarshall}, 653 {"nativeAppendFrom", "(IIII)V", (void*)android_os_Parcel_appendFrom}, 654 {"nativeHasFileDescriptors", "(I)Z", (void*)android_os_Parcel_hasFileDescriptors}, 655 {"nativeWriteInterfaceToken", "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 656 {"nativeEnforceInterface", "(ILjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 657}; 658 659const char* const kParcelPathName = "android/os/Parcel"; 660 661int register_android_os_Parcel(JNIEnv* env) 662{ 663 jclass clazz; 664 665 clazz = env->FindClass(kParcelPathName); 666 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 667 668 gParcelOffsets.mNativePtr 669 = env->GetFieldID(clazz, "mNativePtr", "I"); 670 671 return AndroidRuntime::registerNativeMethods( 672 env, kParcelPathName, 673 gParcelMethods, NELEM(gParcelMethods)); 674} 675 676}; 677