android_os_Parcel.cpp revision d84e1ce0b535128f03416145554fb405f9fade3e
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 mObject; 65 jfieldID mOwnObject; 66} gParcelOffsets; 67 68Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) 69{ 70 if (obj) { 71 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject); 72 if (p != NULL) { 73 return p; 74 } 75 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!"); 76 } 77 return NULL; 78} 79 80static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz) 81{ 82 Parcel* parcel = parcelForJavaObject(env, clazz); 83 return parcel ? parcel->dataSize() : 0; 84} 85 86static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz) 87{ 88 Parcel* parcel = parcelForJavaObject(env, clazz); 89 return parcel ? parcel->dataAvail() : 0; 90} 91 92static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz) 93{ 94 Parcel* parcel = parcelForJavaObject(env, clazz); 95 return parcel ? parcel->dataPosition() : 0; 96} 97 98static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz) 99{ 100 Parcel* parcel = parcelForJavaObject(env, clazz); 101 return parcel ? parcel->dataCapacity() : 0; 102} 103 104static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size) 105{ 106 Parcel* parcel = parcelForJavaObject(env, clazz); 107 if (parcel != NULL) { 108 const status_t err = parcel->setDataSize(size); 109 if (err != NO_ERROR) { 110 signalExceptionForError(env, clazz, err); 111 } 112 } 113} 114 115static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos) 116{ 117 Parcel* parcel = parcelForJavaObject(env, clazz); 118 if (parcel != NULL) { 119 parcel->setDataPosition(pos); 120 } 121} 122 123static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size) 124{ 125 Parcel* parcel = parcelForJavaObject(env, clazz); 126 if (parcel != NULL) { 127 const status_t err = parcel->setDataCapacity(size); 128 if (err != NO_ERROR) { 129 signalExceptionForError(env, clazz, err); 130 } 131 } 132} 133 134static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds) 135{ 136 Parcel* parcel = parcelForJavaObject(env, clazz); 137 jboolean ret = JNI_TRUE; 138 if (parcel != NULL) { 139 ret = (jboolean)parcel->pushAllowFds(allowFds); 140 } 141 return ret; 142} 143 144static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue) 145{ 146 Parcel* parcel = parcelForJavaObject(env, clazz); 147 if (parcel != NULL) { 148 parcel->restoreAllowFds((bool)lastValue); 149 } 150} 151 152static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, 153 jobject data, jint offset, 154 jint length) 155{ 156 Parcel* parcel = parcelForJavaObject(env, clazz); 157 if (parcel == NULL) { 158 return; 159 } 160 161 const status_t err = parcel->writeInt32(length); 162 if (err != NO_ERROR) { 163 signalExceptionForError(env, clazz, err); 164 return; 165 } 166 167 void* dest = parcel->writeInplace(length); 168 if (dest == NULL) { 169 signalExceptionForError(env, clazz, NO_MEMORY); 170 return; 171 } 172 173 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 174 if (ar) { 175 memcpy(dest, ar + offset, length); 176 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 177 } 178} 179 180 181static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 182{ 183 Parcel* parcel = parcelForJavaObject(env, clazz); 184 if (parcel != NULL) { 185 const status_t err = parcel->writeInt32(val); 186 if (err != NO_ERROR) { 187 signalExceptionForError(env, clazz, err); 188 } 189 } 190} 191 192static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 193{ 194 Parcel* parcel = parcelForJavaObject(env, clazz); 195 if (parcel != NULL) { 196 const status_t err = parcel->writeInt64(val); 197 if (err != NO_ERROR) { 198 signalExceptionForError(env, clazz, err); 199 } 200 } 201} 202 203static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 204{ 205 Parcel* parcel = parcelForJavaObject(env, clazz); 206 if (parcel != NULL) { 207 const status_t err = parcel->writeFloat(val); 208 if (err != NO_ERROR) { 209 signalExceptionForError(env, clazz, err); 210 } 211 } 212} 213 214static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 215{ 216 Parcel* parcel = parcelForJavaObject(env, clazz); 217 if (parcel != NULL) { 218 const status_t err = parcel->writeDouble(val); 219 if (err != NO_ERROR) { 220 signalExceptionForError(env, clazz, err); 221 } 222 } 223} 224 225static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 226{ 227 Parcel* parcel = parcelForJavaObject(env, clazz); 228 if (parcel != NULL) { 229 status_t err = NO_MEMORY; 230 if (val) { 231 const jchar* str = env->GetStringCritical(val, 0); 232 if (str) { 233 err = parcel->writeString16(str, env->GetStringLength(val)); 234 env->ReleaseStringCritical(val, str); 235 } 236 } else { 237 err = parcel->writeString16(NULL, 0); 238 } 239 if (err != NO_ERROR) { 240 signalExceptionForError(env, clazz, err); 241 } 242 } 243} 244 245static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 246{ 247 Parcel* parcel = parcelForJavaObject(env, clazz); 248 if (parcel != NULL) { 249 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 250 if (err != NO_ERROR) { 251 signalExceptionForError(env, clazz, err); 252 } 253 } 254} 255 256static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 257{ 258 Parcel* parcel = parcelForJavaObject(env, clazz); 259 if (parcel != NULL) { 260 const status_t err = 261 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object)); 262 if (err != NO_ERROR) { 263 signalExceptionForError(env, clazz, err); 264 } 265 } 266} 267 268static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 269{ 270 jbyteArray ret = NULL; 271 272 Parcel* parcel = parcelForJavaObject(env, clazz); 273 if (parcel != NULL) { 274 int32_t len = parcel->readInt32(); 275 276 // sanity check the stored length against the true data size 277 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 278 ret = env->NewByteArray(len); 279 280 if (ret != NULL) { 281 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 282 if (a2) { 283 const void* data = parcel->readInplace(len); 284 memcpy(a2, data, len); 285 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 286 } 287 } 288 } 289 } 290 291 return ret; 292} 293 294static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 295{ 296 Parcel* parcel = parcelForJavaObject(env, clazz); 297 if (parcel != NULL) { 298 return parcel->readInt32(); 299 } 300 return 0; 301} 302 303static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 304{ 305 Parcel* parcel = parcelForJavaObject(env, clazz); 306 if (parcel != NULL) { 307 return parcel->readInt64(); 308 } 309 return 0; 310} 311 312static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 313{ 314 Parcel* parcel = parcelForJavaObject(env, clazz); 315 if (parcel != NULL) { 316 return parcel->readFloat(); 317 } 318 return 0; 319} 320 321static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 322{ 323 Parcel* parcel = parcelForJavaObject(env, clazz); 324 if (parcel != NULL) { 325 return parcel->readDouble(); 326 } 327 return 0; 328} 329 330static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 331{ 332 Parcel* parcel = parcelForJavaObject(env, clazz); 333 if (parcel != NULL) { 334 size_t len; 335 const char16_t* str = parcel->readString16Inplace(&len); 336 if (str) { 337 return env->NewString(str, len); 338 } 339 return NULL; 340 } 341 return NULL; 342} 343 344static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 345{ 346 Parcel* parcel = parcelForJavaObject(env, clazz); 347 if (parcel != NULL) { 348 return javaObjectForIBinder(env, parcel->readStrongBinder()); 349 } 350 return NULL; 351} 352 353static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 354{ 355 Parcel* parcel = parcelForJavaObject(env, clazz); 356 if (parcel != NULL) { 357 int fd = parcel->readFileDescriptor(); 358 if (fd < 0) return NULL; 359 fd = dup(fd); 360 if (fd < 0) return NULL; 361 return jniCreateFileDescriptor(env, fd); 362 } 363 return NULL; 364} 365 366static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 367 jstring name, jint mode) 368{ 369 if (name == NULL) { 370 jniThrowNullPointerException(env, NULL); 371 return NULL; 372 } 373 const jchar* str = env->GetStringCritical(name, 0); 374 if (str == NULL) { 375 // Whatever, whatever. 376 jniThrowException(env, "java/lang/IllegalStateException", NULL); 377 return NULL; 378 } 379 String8 name8(str, env->GetStringLength(name)); 380 env->ReleaseStringCritical(name, str); 381 int flags=0; 382 switch (mode&0x30000000) { 383 case 0: 384 case 0x10000000: 385 flags = O_RDONLY; 386 break; 387 case 0x20000000: 388 flags = O_WRONLY; 389 break; 390 case 0x30000000: 391 flags = O_RDWR; 392 break; 393 } 394 395 if (mode&0x08000000) flags |= O_CREAT; 396 if (mode&0x04000000) flags |= O_TRUNC; 397 if (mode&0x02000000) flags |= O_APPEND; 398 399 int realMode = S_IRWXU|S_IRWXG; 400 if (mode&0x00000001) realMode |= S_IROTH; 401 if (mode&0x00000002) realMode |= S_IWOTH; 402 403 int fd = open(name8.string(), flags, realMode); 404 if (fd < 0) { 405 jniThrowException(env, "java/io/FileNotFoundException", strerror(errno)); 406 return NULL; 407 } 408 jobject object = jniCreateFileDescriptor(env, fd); 409 if (object == NULL) { 410 close(fd); 411 } 412 return object; 413} 414 415static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig) 416{ 417 if (orig == NULL) { 418 jniThrowNullPointerException(env, NULL); 419 return NULL; 420 } 421 int origfd = jniGetFDFromFileDescriptor(env, orig); 422 if (origfd < 0) { 423 jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor"); 424 return NULL; 425 } 426 427 int fd = dup(origfd); 428 if (fd < 0) { 429 jniThrowIOException(env, errno); 430 return NULL; 431 } 432 jobject object = jniCreateFileDescriptor(env, fd); 433 if (object == NULL) { 434 close(fd); 435 } 436 return object; 437} 438 439static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 440{ 441 if (object == NULL) { 442 jniThrowNullPointerException(env, NULL); 443 return; 444 } 445 int fd = jniGetFDFromFileDescriptor(env, object); 446 if (fd >= 0) { 447 jniSetFileDescriptorOfFD(env, object, -1); 448 //ALOGI("Closing ParcelFileDescriptor %d\n", fd); 449 close(fd); 450 } 451} 452 453static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 454{ 455 if (object == NULL) { 456 jniThrowNullPointerException(env, NULL); 457 return; 458 } 459 int fd = jniGetFDFromFileDescriptor(env, object); 460 if (fd >= 0) { 461 jniSetFileDescriptorOfFD(env, object, -1); 462 } 463} 464 465static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 466{ 467 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 468 if (own) { 469 Parcel* parcel = parcelForJavaObject(env, clazz); 470 if (parcel != NULL) { 471 //ALOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 472 parcel->freeData(); 473 } 474 } 475} 476 477static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 478{ 479 Parcel* parcel = (Parcel*)parcelInt; 480 int own = 0; 481 if (!parcel) { 482 //ALOGI("Initializing obj %p: creating new Parcel\n", clazz); 483 own = 1; 484 parcel = new Parcel; 485 } else { 486 //ALOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 487 } 488 if (parcel == NULL) { 489 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 490 return; 491 } 492 //ALOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 493 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 494 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 495} 496 497static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 498{ 499 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 500 if (own) { 501 Parcel* parcel = parcelForJavaObject(env, clazz); 502 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 503 //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 504 delete parcel; 505 } else { 506 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 507 //ALOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 508 } 509} 510 511static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 512{ 513 Parcel* parcel = parcelForJavaObject(env, clazz); 514 if (parcel == NULL) { 515 return NULL; 516 } 517 518 // do not marshall if there are binder objects in the parcel 519 if (parcel->objectsCount()) 520 { 521 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 522 return NULL; 523 } 524 525 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 526 527 if (ret != NULL) 528 { 529 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 530 if (array != NULL) 531 { 532 memcpy(array, parcel->data(), parcel->dataSize()); 533 env->ReleasePrimitiveArrayCritical(ret, array, 0); 534 } 535 } 536 537 return ret; 538} 539 540static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 541{ 542 Parcel* parcel = parcelForJavaObject(env, clazz); 543 if (parcel == NULL || length < 0) { 544 return; 545 } 546 547 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 548 if (array) 549 { 550 parcel->setDataSize(length); 551 parcel->setDataPosition(0); 552 553 void* raw = parcel->writeInplace(length); 554 memcpy(raw, (array + offset), length); 555 556 env->ReleasePrimitiveArrayCritical(data, array, 0); 557 } 558} 559 560static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 561{ 562 Parcel* thisParcel = parcelForJavaObject(env, clazz); 563 if (thisParcel == NULL) { 564 return; 565 } 566 Parcel* otherParcel = parcelForJavaObject(env, parcel); 567 if (otherParcel == NULL) { 568 return; 569 } 570 571 status_t err = thisParcel->appendFrom(otherParcel, offset, length); 572 if (err != NO_ERROR) { 573 signalExceptionForError(env, clazz, err); 574 } 575} 576 577static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 578{ 579 jboolean ret = JNI_FALSE; 580 Parcel* parcel = parcelForJavaObject(env, clazz); 581 if (parcel != NULL) { 582 if (parcel->hasFileDescriptors()) { 583 ret = JNI_TRUE; 584 } 585 } 586 return ret; 587} 588 589static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 590{ 591 Parcel* parcel = parcelForJavaObject(env, clazz); 592 if (parcel != NULL) { 593 // In the current implementation, the token is just the serialized interface name that 594 // the caller expects to be invoking 595 const jchar* str = env->GetStringCritical(name, 0); 596 if (str != NULL) { 597 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 598 env->ReleaseStringCritical(name, str); 599 } 600 } 601} 602 603static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 604{ 605 jboolean ret = JNI_FALSE; 606 607 Parcel* parcel = parcelForJavaObject(env, clazz); 608 if (parcel != NULL) { 609 const jchar* str = env->GetStringCritical(name, 0); 610 if (str) { 611 IPCThreadState* threadState = IPCThreadState::self(); 612 const int32_t oldPolicy = threadState->getStrictModePolicy(); 613 const bool isValid = parcel->enforceInterface( 614 String16(str, env->GetStringLength(name)), 615 threadState); 616 env->ReleaseStringCritical(name, str); 617 if (isValid) { 618 const int32_t newPolicy = threadState->getStrictModePolicy(); 619 if (oldPolicy != newPolicy) { 620 // Need to keep the Java-level thread-local strict 621 // mode policy in sync for the libcore 622 // enforcements, which involves an upcall back 623 // into Java. (We can't modify the 624 // Parcel.enforceInterface signature, as it's 625 // pseudo-public, and used via AIDL 626 // auto-generation...) 627 set_dalvik_blockguard_policy(env, newPolicy); 628 } 629 return; // everything was correct -> return silently 630 } 631 } 632 } 633 634 // all error conditions wind up here 635 jniThrowException(env, "java/lang/SecurityException", 636 "Binder invocation to an incorrect interface"); 637} 638 639// ---------------------------------------------------------------------------- 640 641static const JNINativeMethod gParcelMethods[] = { 642 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 643 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 644 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 645 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 646 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 647 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 648 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 649 {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds}, 650 {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds}, 651 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 652 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 653 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 654 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 655 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 656 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 657 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 658 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 659 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 660 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 661 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 662 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 663 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 664 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 665 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 666 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 667 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 668 {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor}, 669 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 670 {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor}, 671 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 672 {"init", "(I)V", (void*)android_os_Parcel_init}, 673 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 674 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 675 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 676 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 677 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 678 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 679 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 680}; 681 682const char* const kParcelPathName = "android/os/Parcel"; 683 684int register_android_os_Parcel(JNIEnv* env) 685{ 686 jclass clazz; 687 688 clazz = env->FindClass(kParcelPathName); 689 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 690 691 gParcelOffsets.mObject 692 = env->GetFieldID(clazz, "mObject", "I"); 693 gParcelOffsets.mOwnObject 694 = env->GetFieldID(clazz, "mOwnObject", "I"); 695 696 return AndroidRuntime::registerNativeMethods( 697 env, kParcelPathName, 698 gParcelMethods, NELEM(gParcelMethods)); 699} 700 701}; 702