android_util_Binder.cpp revision 5348c014129b766d621ef82a6e42007009ffc310
1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* 2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Copyright (C) 2006 The Android Open Source Project 3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Licensed under the Apache License, Version 2.0 (the "License"); 5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * you may not use this file except in compliance with the License. 6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * You may obtain a copy of the License at 7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * http://www.apache.org/licenses/LICENSE-2.0 9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * 10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * Unless required by applicable law or agreed to in writing, software 11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * distributed under the License is distributed on an "AS IS" BASIS, 12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * See the License for the specific language governing permissions and 14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov * limitations under the License. 15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov */ 16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define LOG_TAG "JavaBinder" 18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//#define LOG_NDEBUG 0 19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "android_util_Binder.h" 21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "JNIHelp.h" 22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <fcntl.h> 24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <stdio.h> 25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <sys/stat.h> 26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <sys/types.h> 27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <unistd.h> 28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <utils/Atomic.h> 30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <binder/IInterface.h> 31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <binder/IPCThreadState.h> 32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <utils/Log.h> 33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <utils/SystemClock.h> 34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <cutils/logger.h> 35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <binder/Parcel.h> 36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <binder/ProcessState.h> 37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <binder/IServiceManager.h> 38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <utils/threads.h> 39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include <android_runtime/AndroidRuntime.h> 41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//#undef LOGV 43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//#define LOGV(...) fprintf(stderr, __VA_ARGS__) 44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovusing namespace android; 46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ---------------------------------------------------------------------------- 48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic struct bindernative_offsets_t 50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Class state. 52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jclass mClass; 53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jmethodID mExecTransact; 54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Object state. 56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jfieldID mObject; 57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} gBinderOffsets; 59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ---------------------------------------------------------------------------- 61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic struct binderinternal_offsets_t 63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Class state. 65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jclass mClass; 66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jmethodID mForceGc; 67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} gBinderInternalOffsets; 69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ---------------------------------------------------------------------------- 71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov 72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic struct debug_offsets_t 73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{ 74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov // Class state. 75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov jclass mClass; 76 77} gDebugOffsets; 78 79// ---------------------------------------------------------------------------- 80 81static struct weakreference_offsets_t 82{ 83 // Class state. 84 jclass mClass; 85 jmethodID mGet; 86 87} gWeakReferenceOffsets; 88 89static struct error_offsets_t 90{ 91 jclass mClass; 92} gErrorOffsets; 93 94// ---------------------------------------------------------------------------- 95 96static struct binderproxy_offsets_t 97{ 98 // Class state. 99 jclass mClass; 100 jmethodID mConstructor; 101 jmethodID mSendDeathNotice; 102 103 // Object state. 104 jfieldID mObject; 105 jfieldID mSelf; 106 107} gBinderProxyOffsets; 108 109// ---------------------------------------------------------------------------- 110 111static struct parcel_offsets_t 112{ 113 jfieldID mObject; 114 jfieldID mOwnObject; 115} gParcelOffsets; 116 117static struct log_offsets_t 118{ 119 // Class state. 120 jclass mClass; 121 jmethodID mLogE; 122} gLogOffsets; 123 124static struct file_descriptor_offsets_t 125{ 126 jclass mClass; 127 jmethodID mConstructor; 128 jfieldID mDescriptor; 129} gFileDescriptorOffsets; 130 131static struct parcel_file_descriptor_offsets_t 132{ 133 jclass mClass; 134 jmethodID mConstructor; 135} gParcelFileDescriptorOffsets; 136 137// **************************************************************************** 138// **************************************************************************** 139// **************************************************************************** 140 141static volatile int32_t gNumRefsCreated = 0; 142static volatile int32_t gNumProxyRefs = 0; 143static volatile int32_t gNumLocalRefs = 0; 144static volatile int32_t gNumDeathRefs = 0; 145 146static void incRefsCreated(JNIEnv* env) 147{ 148 int old = android_atomic_inc(&gNumRefsCreated); 149 if (old == 200) { 150 android_atomic_and(0, &gNumRefsCreated); 151 env->CallStaticVoidMethod(gBinderInternalOffsets.mClass, 152 gBinderInternalOffsets.mForceGc); 153 } else { 154 LOGV("Now have %d binder ops", old); 155 } 156} 157 158static JavaVM* jnienv_to_javavm(JNIEnv* env) 159{ 160 JavaVM* vm; 161 return env->GetJavaVM(&vm) >= 0 ? vm : NULL; 162} 163 164static JNIEnv* javavm_to_jnienv(JavaVM* vm) 165{ 166 JNIEnv* env; 167 return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; 168} 169 170static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) 171{ 172 env->ExceptionClear(); 173 174 jstring tagstr = env->NewStringUTF(LOG_TAG); 175 jstring msgstr = env->NewStringUTF(msg); 176 177 if ((tagstr == NULL) || (msgstr == NULL)) { 178 env->ExceptionClear(); /* assume exception (OOM?) was thrown */ 179 LOGE("Unable to call Log.e()\n"); 180 LOGE("%s", msg); 181 goto bail; 182 } 183 184 env->CallStaticIntMethod( 185 gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); 186 if (env->ExceptionCheck()) { 187 /* attempting to log the failure has failed */ 188 LOGW("Failed trying to log exception, msg='%s'\n", msg); 189 env->ExceptionClear(); 190 } 191 192 if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { 193 /* 194 * It's an Error: Reraise the exception, detach this thread, and 195 * wait for the fireworks. Die even more blatantly after a minute 196 * if the gentler attempt doesn't do the trick. 197 * 198 * The GetJavaVM function isn't on the "approved" list of JNI calls 199 * that can be made while an exception is pending, so we want to 200 * get the VM ptr, throw the exception, and then detach the thread. 201 */ 202 JavaVM* vm = jnienv_to_javavm(env); 203 env->Throw(excep); 204 vm->DetachCurrentThread(); 205 sleep(60); 206 LOGE("Forcefully exiting"); 207 exit(1); 208 *((int *) 1) = 1; 209 } 210 211bail: 212 /* discard local refs created for us by VM */ 213 env->DeleteLocalRef(tagstr); 214 env->DeleteLocalRef(msgstr); 215} 216 217class JavaBBinderHolder; 218 219class JavaBBinder : public BBinder 220{ 221public: 222 JavaBBinder(JNIEnv* env, jobject object) 223 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) 224 { 225 LOGV("Creating JavaBBinder %p\n", this); 226 android_atomic_inc(&gNumLocalRefs); 227 incRefsCreated(env); 228 } 229 230 bool checkSubclass(const void* subclassID) const 231 { 232 return subclassID == &gBinderOffsets; 233 } 234 235 jobject object() const 236 { 237 return mObject; 238 } 239 240protected: 241 virtual ~JavaBBinder() 242 { 243 LOGV("Destroying JavaBBinder %p\n", this); 244 android_atomic_dec(&gNumLocalRefs); 245 JNIEnv* env = javavm_to_jnienv(mVM); 246 env->DeleteGlobalRef(mObject); 247 } 248 249 virtual status_t onTransact( 250 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) 251 { 252 JNIEnv* env = javavm_to_jnienv(mVM); 253 254 LOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM); 255 256 //printf("Transact from %p to Java code sending: ", this); 257 //data.print(); 258 //printf("\n"); 259 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, 260 code, (int32_t)&data, (int32_t)reply, flags); 261 jthrowable excep = env->ExceptionOccurred(); 262 if (excep) { 263 report_exception(env, excep, 264 "*** Uncaught remote exception! " 265 "(Exceptions are not yet supported across processes.)"); 266 res = JNI_FALSE; 267 268 /* clean up JNI local ref -- we don't return to Java code */ 269 env->DeleteLocalRef(excep); 270 } 271 272 //aout << "onTransact to Java code; result=" << res << endl 273 // << "Transact from " << this << " to Java code returning " 274 // << reply << ": " << *reply << endl; 275 return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; 276 } 277 278 virtual status_t dump(int fd, const Vector<String16>& args) 279 { 280 return 0; 281 } 282 283private: 284 JavaVM* const mVM; 285 jobject const mObject; 286}; 287 288// ---------------------------------------------------------------------------- 289 290class JavaBBinderHolder : public RefBase 291{ 292public: 293 JavaBBinderHolder(JNIEnv* env, jobject object) 294 : mObject(object) 295 { 296 LOGV("Creating JavaBBinderHolder for Object %p\n", object); 297 } 298 ~JavaBBinderHolder() 299 { 300 LOGV("Destroying JavaBBinderHolder for Object %p\n", mObject); 301 } 302 303 sp<JavaBBinder> get(JNIEnv* env) 304 { 305 AutoMutex _l(mLock); 306 sp<JavaBBinder> b = mBinder.promote(); 307 if (b == NULL) { 308 b = new JavaBBinder(env, mObject); 309 mBinder = b; 310 LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n", 311 b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount()); 312 } 313 314 return b; 315 } 316 317 sp<JavaBBinder> getExisting() 318 { 319 AutoMutex _l(mLock); 320 return mBinder.promote(); 321 } 322 323private: 324 Mutex mLock; 325 jobject mObject; 326 wp<JavaBBinder> mBinder; 327}; 328 329// ---------------------------------------------------------------------------- 330 331class JavaDeathRecipient : public IBinder::DeathRecipient 332{ 333public: 334 JavaDeathRecipient(JNIEnv* env, jobject object) 335 : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), 336 mHoldsRef(true) 337 { 338 incStrong(this); 339 android_atomic_inc(&gNumDeathRefs); 340 incRefsCreated(env); 341 } 342 343 void binderDied(const wp<IBinder>& who) 344 { 345 JNIEnv* env = javavm_to_jnienv(mVM); 346 347 LOGV("Receiving binderDied() on JavaDeathRecipient %p\n", this); 348 349 env->CallStaticVoidMethod(gBinderProxyOffsets.mClass, 350 gBinderProxyOffsets.mSendDeathNotice, mObject); 351 jthrowable excep = env->ExceptionOccurred(); 352 if (excep) { 353 report_exception(env, excep, 354 "*** Uncaught exception returned from death notification!"); 355 } 356 357 clearReference(); 358 } 359 360 void clearReference() 361 { 362 bool release = false; 363 mLock.lock(); 364 if (mHoldsRef) { 365 mHoldsRef = false; 366 release = true; 367 } 368 mLock.unlock(); 369 if (release) { 370 decStrong(this); 371 } 372 } 373 374protected: 375 virtual ~JavaDeathRecipient() 376 { 377 //LOGI("Removing death ref: recipient=%p\n", mObject); 378 android_atomic_dec(&gNumDeathRefs); 379 JNIEnv* env = javavm_to_jnienv(mVM); 380 env->DeleteGlobalRef(mObject); 381 } 382 383private: 384 JavaVM* const mVM; 385 jobject const mObject; 386 Mutex mLock; 387 bool mHoldsRef; 388}; 389 390// ---------------------------------------------------------------------------- 391 392namespace android { 393 394static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) 395{ 396 android_atomic_dec(&gNumProxyRefs); 397 JNIEnv* env = javavm_to_jnienv((JavaVM*)cleanupCookie); 398 env->DeleteGlobalRef((jobject)obj); 399} 400 401static Mutex mProxyLock; 402 403jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) 404{ 405 if (val == NULL) return NULL; 406 407 if (val->checkSubclass(&gBinderOffsets)) { 408 // One of our own! 409 jobject object = static_cast<JavaBBinder*>(val.get())->object(); 410 //printf("objectForBinder %p: it's our own %p!\n", val.get(), object); 411 return object; 412 } 413 414 // For the rest of the function we will hold this lock, to serialize 415 // looking/creation of Java proxies for native Binder proxies. 416 AutoMutex _l(mProxyLock); 417 418 // Someone else's... do we know about it? 419 jobject object = (jobject)val->findObject(&gBinderProxyOffsets); 420 if (object != NULL) { 421 jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet); 422 if (res != NULL) { 423 LOGV("objectForBinder %p: found existing %p!\n", val.get(), res); 424 return res; 425 } 426 LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get()); 427 android_atomic_dec(&gNumProxyRefs); 428 val->detachObject(&gBinderProxyOffsets); 429 env->DeleteGlobalRef(object); 430 } 431 432 object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); 433 if (object != NULL) { 434 LOGV("objectForBinder %p: created new %p!\n", val.get(), object); 435 // The proxy holds a reference to the native object. 436 env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get()); 437 val->incStrong(object); 438 439 // The native object needs to hold a weak reference back to the 440 // proxy, so we can retrieve the same proxy if it is still active. 441 jobject refObject = env->NewGlobalRef( 442 env->GetObjectField(object, gBinderProxyOffsets.mSelf)); 443 val->attachObject(&gBinderProxyOffsets, refObject, 444 jnienv_to_javavm(env), proxy_cleanup); 445 446 // Note that a new object reference has been created. 447 android_atomic_inc(&gNumProxyRefs); 448 incRefsCreated(env); 449 } 450 451 return object; 452} 453 454sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) 455{ 456 if (obj == NULL) return NULL; 457 458 if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { 459 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 460 env->GetIntField(obj, gBinderOffsets.mObject); 461 return jbh != NULL ? jbh->get(env) : NULL; 462 } 463 464 if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { 465 return (IBinder*) 466 env->GetIntField(obj, gBinderProxyOffsets.mObject); 467 } 468 469 LOGW("ibinderForJavaObject: %p is not a Binder object", obj); 470 return NULL; 471} 472 473Parcel* parcelForJavaObject(JNIEnv* env, jobject obj) 474{ 475 if (obj) { 476 Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject); 477 if (p != NULL) { 478 return p; 479 } 480 jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!"); 481 } 482 return NULL; 483} 484 485jobject newFileDescriptor(JNIEnv* env, int fd) 486{ 487 jobject object = env->NewObject( 488 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 489 if (object != NULL) { 490 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 491 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 492 } 493 return object; 494} 495 496jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc) 497{ 498 return env->NewObject( 499 gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc); 500} 501 502void signalExceptionForError(JNIEnv* env, jobject obj, status_t err) 503{ 504 switch (err) { 505 case UNKNOWN_ERROR: 506 jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); 507 break; 508 case NO_MEMORY: 509 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 510 break; 511 case INVALID_OPERATION: 512 jniThrowException(env, "java/lang/UnsupportedOperationException", NULL); 513 break; 514 case BAD_VALUE: 515 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 516 break; 517 case BAD_INDEX: 518 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 519 break; 520 case BAD_TYPE: 521 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 522 break; 523 case NAME_NOT_FOUND: 524 jniThrowException(env, "java/util/NoSuchElementException", NULL); 525 break; 526 case PERMISSION_DENIED: 527 jniThrowException(env, "java/lang/SecurityException", NULL); 528 break; 529 case NOT_ENOUGH_DATA: 530 jniThrowException(env, "android/os/ParcelFormatException", "Not enough data"); 531 break; 532 case NO_INIT: 533 jniThrowException(env, "java/lang/RuntimeException", "Not initialized"); 534 break; 535 case ALREADY_EXISTS: 536 jniThrowException(env, "java/lang/RuntimeException", "Item already exists"); 537 break; 538 case DEAD_OBJECT: 539 jniThrowException(env, "android/os/DeadObjectException", NULL); 540 break; 541 case UNKNOWN_TRANSACTION: 542 jniThrowException(env, "java/lang/RuntimeException", "Unknown transaction code"); 543 break; 544 case FAILED_TRANSACTION: 545 LOGE("!!! FAILED BINDER TRANSACTION !!!"); 546 //jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large"); 547 break; 548 default: 549 LOGE("Unknown binder error code. 0x%x", err); 550 } 551} 552 553} 554 555// ---------------------------------------------------------------------------- 556 557static jint android_os_Binder_getCallingPid(JNIEnv* env, jobject clazz) 558{ 559 return IPCThreadState::self()->getCallingPid(); 560} 561 562static jint android_os_Binder_getCallingUid(JNIEnv* env, jobject clazz) 563{ 564 return IPCThreadState::self()->getCallingUid(); 565} 566 567static jlong android_os_Binder_clearCallingIdentity(JNIEnv* env, jobject clazz) 568{ 569 return IPCThreadState::self()->clearCallingIdentity(); 570} 571 572static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token) 573{ 574 IPCThreadState::self()->restoreCallingIdentity(token); 575} 576 577static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) 578{ 579 IPCThreadState::self()->flushCommands(); 580} 581 582static void android_os_Binder_init(JNIEnv* env, jobject clazz) 583{ 584 JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); 585 if (jbh == NULL) { 586 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 587 return; 588 } 589 LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); 590 jbh->incStrong(clazz); 591 env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); 592} 593 594static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) 595{ 596 JavaBBinderHolder* jbh = (JavaBBinderHolder*) 597 env->GetIntField(clazz, gBinderOffsets.mObject); 598 if (jbh != NULL) { 599 env->SetIntField(clazz, gBinderOffsets.mObject, 0); 600 LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh); 601 jbh->decStrong(clazz); 602 } else { 603 // Encountering an uninitialized binder is harmless. All it means is that 604 // the Binder was only partially initialized when its finalizer ran and called 605 // destroy(). The Binder could be partially initialized for several reasons. 606 // For example, a Binder subclass constructor might have thrown an exception before 607 // it could delegate to its superclass's constructor. Consequently init() would 608 // not have been called and the holder pointer would remain NULL. 609 LOGV("Java Binder %p: ignoring uninitialized binder", clazz); 610 } 611} 612 613// ---------------------------------------------------------------------------- 614 615static const JNINativeMethod gBinderMethods[] = { 616 /* name, signature, funcPtr */ 617 { "getCallingPid", "()I", (void*)android_os_Binder_getCallingPid }, 618 { "getCallingUid", "()I", (void*)android_os_Binder_getCallingUid }, 619 { "clearCallingIdentity", "()J", (void*)android_os_Binder_clearCallingIdentity }, 620 { "restoreCallingIdentity", "(J)V", (void*)android_os_Binder_restoreCallingIdentity }, 621 { "flushPendingCommands", "()V", (void*)android_os_Binder_flushPendingCommands }, 622 { "init", "()V", (void*)android_os_Binder_init }, 623 { "destroy", "()V", (void*)android_os_Binder_destroy } 624}; 625 626const char* const kBinderPathName = "android/os/Binder"; 627 628static int int_register_android_os_Binder(JNIEnv* env) 629{ 630 jclass clazz; 631 632 clazz = env->FindClass(kBinderPathName); 633 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder"); 634 635 gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 636 gBinderOffsets.mExecTransact 637 = env->GetMethodID(clazz, "execTransact", "(IIII)Z"); 638 assert(gBinderOffsets.mExecTransact); 639 640 gBinderOffsets.mObject 641 = env->GetFieldID(clazz, "mObject", "I"); 642 assert(gBinderOffsets.mObject); 643 644 return AndroidRuntime::registerNativeMethods( 645 env, kBinderPathName, 646 gBinderMethods, NELEM(gBinderMethods)); 647} 648 649// **************************************************************************** 650// **************************************************************************** 651// **************************************************************************** 652 653namespace android { 654 655jint android_os_Debug_getLocalObjectCount(JNIEnv* env, jobject clazz) 656{ 657 return gNumLocalRefs; 658} 659 660jint android_os_Debug_getProxyObjectCount(JNIEnv* env, jobject clazz) 661{ 662 return gNumProxyRefs; 663} 664 665jint android_os_Debug_getDeathObjectCount(JNIEnv* env, jobject clazz) 666{ 667 return gNumDeathRefs; 668} 669 670} 671 672// **************************************************************************** 673// **************************************************************************** 674// **************************************************************************** 675 676static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz) 677{ 678 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 679 return javaObjectForIBinder(env, b); 680} 681 682static void android_os_BinderInternal_joinThreadPool(JNIEnv* env, jobject clazz) 683{ 684 sp<IBinder> b = ProcessState::self()->getContextObject(NULL); 685 android::IPCThreadState::self()->joinThreadPool(); 686} 687 688static void android_os_BinderInternal_disableBackgroundScheduling(JNIEnv* env, 689 jobject clazz, jboolean disable) 690{ 691 IPCThreadState::disableBackgroundScheduling(disable ? true : false); 692} 693 694static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz) 695{ 696 LOGV("Gc has executed, clearing binder ops"); 697 android_atomic_and(0, &gNumRefsCreated); 698} 699 700// ---------------------------------------------------------------------------- 701 702static const JNINativeMethod gBinderInternalMethods[] = { 703 /* name, signature, funcPtr */ 704 { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject }, 705 { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool }, 706 { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling }, 707 { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc } 708}; 709 710const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal"; 711 712static int int_register_android_os_BinderInternal(JNIEnv* env) 713{ 714 jclass clazz; 715 716 clazz = env->FindClass(kBinderInternalPathName); 717 LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal"); 718 719 gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 720 gBinderInternalOffsets.mForceGc 721 = env->GetStaticMethodID(clazz, "forceBinderGc", "()V"); 722 assert(gBinderInternalOffsets.mForceGc); 723 724 return AndroidRuntime::registerNativeMethods( 725 env, kBinderInternalPathName, 726 gBinderInternalMethods, NELEM(gBinderInternalMethods)); 727} 728 729// **************************************************************************** 730// **************************************************************************** 731// **************************************************************************** 732 733static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) 734{ 735 IBinder* target = (IBinder*) 736 env->GetIntField(obj, gBinderProxyOffsets.mObject); 737 if (target == NULL) { 738 return JNI_FALSE; 739 } 740 status_t err = target->pingBinder(); 741 return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; 742} 743 744static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) 745{ 746 IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); 747 if (target != NULL) { 748 const String16& desc = target->getInterfaceDescriptor(); 749 return env->NewString(desc.string(), desc.size()); 750 } 751 jniThrowException(env, "java/lang/RuntimeException", 752 "No binder found for object"); 753 return NULL; 754} 755 756static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) 757{ 758 IBinder* target = (IBinder*) 759 env->GetIntField(obj, gBinderProxyOffsets.mObject); 760 if (target == NULL) { 761 return JNI_FALSE; 762 } 763 bool alive = target->isBinderAlive(); 764 return alive ? JNI_TRUE : JNI_FALSE; 765} 766 767static int getprocname(pid_t pid, char *buf, size_t len) { 768 char filename[20]; 769 FILE *f; 770 771 sprintf(filename, "/proc/%d/cmdline", pid); 772 f = fopen(filename, "r"); 773 if (!f) { *buf = '\0'; return 1; } 774 if (!fgets(buf, len, f)) { *buf = '\0'; return 2; } 775 fclose(f); 776 return 0; 777} 778 779static bool push_eventlog_string(char** pos, const char* end, const char* str) { 780 jint len = strlen(str); 781 int space_needed = 1 + sizeof(len) + len; 782 if (end - *pos < space_needed) { 783 LOGW("not enough space for string. remain=%d; needed=%d", 784 (end - *pos), space_needed); 785 return false; 786 } 787 **pos = EVENT_TYPE_STRING; 788 (*pos)++; 789 memcpy(*pos, &len, sizeof(len)); 790 *pos += sizeof(len); 791 memcpy(*pos, str, len); 792 *pos += len; 793 return true; 794} 795 796static bool push_eventlog_int(char** pos, const char* end, jint val) { 797 int space_needed = 1 + sizeof(val); 798 if (end - *pos < space_needed) { 799 LOGW("not enough space for int. remain=%d; needed=%d", 800 (end - *pos), space_needed); 801 return false; 802 } 803 **pos = EVENT_TYPE_INT; 804 (*pos)++; 805 memcpy(*pos, &val, sizeof(val)); 806 *pos += sizeof(val); 807 return true; 808} 809 810// From frameworks/base/core/java/android/content/EventLogTags.logtags: 811#define LOGTAG_BINDER_OPERATION 52004 812 813static void conditionally_log_binder_call(int64_t start_millis, 814 IBinder* target, jint code) { 815 int duration_ms = static_cast<int>(uptimeMillis() - start_millis); 816 817 int sample_percent; 818 if (duration_ms >= 500) { 819 sample_percent = 100; 820 } else { 821 sample_percent = 100 * duration_ms / 500; 822 if (sample_percent == 0) { 823 return; 824 } 825 if (sample_percent < (random() % 100 + 1)) { 826 return; 827 } 828 } 829 830 char process_name[40]; 831 getprocname(getpid(), process_name, sizeof(process_name)); 832 String8 desc(target->getInterfaceDescriptor()); 833 834 char buf[LOGGER_ENTRY_MAX_PAYLOAD]; 835 buf[0] = EVENT_TYPE_LIST; 836 buf[1] = 5; 837 char* pos = &buf[2]; 838 char* end = &buf[LOGGER_ENTRY_MAX_PAYLOAD - 1]; // leave room for final \n 839 if (!push_eventlog_string(&pos, end, desc.string())) return; 840 if (!push_eventlog_int(&pos, end, code)) return; 841 if (!push_eventlog_int(&pos, end, duration_ms)) return; 842 if (!push_eventlog_string(&pos, end, process_name)) return; 843 if (!push_eventlog_int(&pos, end, sample_percent)) return; 844 *(pos++) = '\n'; // conventional with EVENT_TYPE_LIST apparently. 845 android_bWriteLog(LOGTAG_BINDER_OPERATION, buf, pos - buf); 846} 847 848// We only measure binder call durations to potentially log them if 849// we're on the main thread. Unfortunately sim-eng doesn't seem to 850// have gettid, so we just ignore this and don't log if we can't 851// get the thread id. 852static bool should_time_binder_calls() { 853#ifdef HAVE_GETTID 854 return (getpid() == androidGetTid()); 855#else 856#warning no gettid(), so not logging Binder calls... 857 return false; 858#endif 859} 860 861static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, 862 jint code, jobject dataObj, 863 jobject replyObj, jint flags) 864{ 865 if (dataObj == NULL) { 866 jniThrowException(env, "java/lang/NullPointerException", NULL); 867 return JNI_FALSE; 868 } 869 870 Parcel* data = parcelForJavaObject(env, dataObj); 871 if (data == NULL) { 872 return JNI_FALSE; 873 } 874 Parcel* reply = parcelForJavaObject(env, replyObj); 875 if (reply == NULL && replyObj != NULL) { 876 return JNI_FALSE; 877 } 878 879 IBinder* target = (IBinder*) 880 env->GetIntField(obj, gBinderProxyOffsets.mObject); 881 if (target == NULL) { 882 jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); 883 return JNI_FALSE; 884 } 885 886 LOGV("Java code calling transact on %p in Java object %p with code %d\n", 887 target, obj, code); 888 889 // Only log the binder call duration for things on the Java-level main thread. 890 // But if we don't 891 const bool time_binder_calls = should_time_binder_calls(); 892 893 int64_t start_millis; 894 if (time_binder_calls) { 895 start_millis = uptimeMillis(); 896 } 897 //printf("Transact from Java code to %p sending: ", target); data->print(); 898 status_t err = target->transact(code, *data, reply, flags); 899 //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); 900 if (time_binder_calls) { 901 conditionally_log_binder_call(start_millis, target, code); 902 } 903 904 if (err == NO_ERROR) { 905 return JNI_TRUE; 906 } else if (err == UNKNOWN_TRANSACTION) { 907 return JNI_FALSE; 908 } 909 910 signalExceptionForError(env, obj, err); 911 return JNI_FALSE; 912} 913 914static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, 915 jobject recipient, jint flags) 916{ 917 if (recipient == NULL) { 918 jniThrowException(env, "java/lang/NullPointerException", NULL); 919 return; 920 } 921 922 IBinder* target = (IBinder*) 923 env->GetIntField(obj, gBinderProxyOffsets.mObject); 924 if (target == NULL) { 925 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 926 assert(false); 927 } 928 929 LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); 930 931 if (!target->localBinder()) { 932 sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient); 933 status_t err = target->linkToDeath(jdr, recipient, flags); 934 if (err != NO_ERROR) { 935 // Failure adding the death recipient, so clear its reference 936 // now. 937 jdr->clearReference(); 938 signalExceptionForError(env, obj, err); 939 } 940 } 941} 942 943static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, 944 jobject recipient, jint flags) 945{ 946 jboolean res = JNI_FALSE; 947 if (recipient == NULL) { 948 jniThrowException(env, "java/lang/NullPointerException", NULL); 949 return res; 950 } 951 952 IBinder* target = (IBinder*) 953 env->GetIntField(obj, gBinderProxyOffsets.mObject); 954 if (target == NULL) { 955 LOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); 956 return JNI_FALSE; 957 } 958 959 LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); 960 961 if (!target->localBinder()) { 962 wp<IBinder::DeathRecipient> dr; 963 status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr); 964 if (err == NO_ERROR && dr != NULL) { 965 sp<IBinder::DeathRecipient> sdr = dr.promote(); 966 JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); 967 if (jdr != NULL) { 968 jdr->clearReference(); 969 } 970 } 971 if (err == NO_ERROR || err == DEAD_OBJECT) { 972 res = JNI_TRUE; 973 } else { 974 jniThrowException(env, "java/util/NoSuchElementException", 975 "Death link does not exist"); 976 } 977 } 978 979 return res; 980} 981 982static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) 983{ 984 IBinder* b = (IBinder*) 985 env->GetIntField(obj, gBinderProxyOffsets.mObject); 986 LOGV("Destroying BinderProxy %p: binder=%p\n", obj, b); 987 env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); 988 b->decStrong(obj); 989 IPCThreadState::self()->flushCommands(); 990} 991 992// ---------------------------------------------------------------------------- 993 994static const JNINativeMethod gBinderProxyMethods[] = { 995 /* name, signature, funcPtr */ 996 {"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder}, 997 {"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive}, 998 {"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor}, 999 {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact}, 1000 {"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath}, 1001 {"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath}, 1002 {"destroy", "()V", (void*)android_os_BinderProxy_destroy}, 1003}; 1004 1005const char* const kBinderProxyPathName = "android/os/BinderProxy"; 1006 1007static int int_register_android_os_BinderProxy(JNIEnv* env) 1008{ 1009 jclass clazz; 1010 1011 clazz = env->FindClass("java/lang/ref/WeakReference"); 1012 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.ref.WeakReference"); 1013 gWeakReferenceOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1014 gWeakReferenceOffsets.mGet 1015 = env->GetMethodID(clazz, "get", "()Ljava/lang/Object;"); 1016 assert(gWeakReferenceOffsets.mGet); 1017 1018 clazz = env->FindClass("java/lang/Error"); 1019 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.lang.Error"); 1020 gErrorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1021 1022 clazz = env->FindClass(kBinderProxyPathName); 1023 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy"); 1024 1025 gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1026 gBinderProxyOffsets.mConstructor 1027 = env->GetMethodID(clazz, "<init>", "()V"); 1028 assert(gBinderProxyOffsets.mConstructor); 1029 gBinderProxyOffsets.mSendDeathNotice 1030 = env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V"); 1031 assert(gBinderProxyOffsets.mSendDeathNotice); 1032 1033 gBinderProxyOffsets.mObject 1034 = env->GetFieldID(clazz, "mObject", "I"); 1035 assert(gBinderProxyOffsets.mObject); 1036 gBinderProxyOffsets.mSelf 1037 = env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;"); 1038 assert(gBinderProxyOffsets.mSelf); 1039 1040 return AndroidRuntime::registerNativeMethods( 1041 env, kBinderProxyPathName, 1042 gBinderProxyMethods, NELEM(gBinderProxyMethods)); 1043} 1044 1045// **************************************************************************** 1046// **************************************************************************** 1047// **************************************************************************** 1048 1049static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz) 1050{ 1051 Parcel* parcel = parcelForJavaObject(env, clazz); 1052 return parcel ? parcel->dataSize() : 0; 1053} 1054 1055static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz) 1056{ 1057 Parcel* parcel = parcelForJavaObject(env, clazz); 1058 return parcel ? parcel->dataAvail() : 0; 1059} 1060 1061static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz) 1062{ 1063 Parcel* parcel = parcelForJavaObject(env, clazz); 1064 return parcel ? parcel->dataPosition() : 0; 1065} 1066 1067static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz) 1068{ 1069 Parcel* parcel = parcelForJavaObject(env, clazz); 1070 return parcel ? parcel->dataCapacity() : 0; 1071} 1072 1073static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size) 1074{ 1075 Parcel* parcel = parcelForJavaObject(env, clazz); 1076 if (parcel != NULL) { 1077 const status_t err = parcel->setDataSize(size); 1078 if (err != NO_ERROR) { 1079 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1080 } 1081 } 1082} 1083 1084static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos) 1085{ 1086 Parcel* parcel = parcelForJavaObject(env, clazz); 1087 if (parcel != NULL) { 1088 parcel->setDataPosition(pos); 1089 } 1090} 1091 1092static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size) 1093{ 1094 Parcel* parcel = parcelForJavaObject(env, clazz); 1095 if (parcel != NULL) { 1096 const status_t err = parcel->setDataCapacity(size); 1097 if (err != NO_ERROR) { 1098 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1099 } 1100 } 1101} 1102 1103static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, 1104 jobject data, jint offset, 1105 jint length) 1106{ 1107 Parcel* parcel = parcelForJavaObject(env, clazz); 1108 if (parcel == NULL) { 1109 return; 1110 } 1111 void *dest; 1112 1113 const status_t err = parcel->writeInt32(length); 1114 if (err != NO_ERROR) { 1115 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1116 } 1117 1118 dest = parcel->writeInplace(length); 1119 1120 if (dest == NULL) { 1121 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1122 return; 1123 } 1124 1125 jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); 1126 if (ar) { 1127 memcpy(dest, ar, length); 1128 env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); 1129 } 1130} 1131 1132 1133static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val) 1134{ 1135 Parcel* parcel = parcelForJavaObject(env, clazz); 1136 if (parcel != NULL) { 1137 const status_t err = parcel->writeInt32(val); 1138 if (err != NO_ERROR) { 1139 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1140 } 1141 } 1142} 1143 1144static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val) 1145{ 1146 Parcel* parcel = parcelForJavaObject(env, clazz); 1147 if (parcel != NULL) { 1148 const status_t err = parcel->writeInt64(val); 1149 if (err != NO_ERROR) { 1150 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1151 } 1152 } 1153} 1154 1155static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val) 1156{ 1157 Parcel* parcel = parcelForJavaObject(env, clazz); 1158 if (parcel != NULL) { 1159 const status_t err = parcel->writeFloat(val); 1160 if (err != NO_ERROR) { 1161 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1162 } 1163 } 1164} 1165 1166static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val) 1167{ 1168 Parcel* parcel = parcelForJavaObject(env, clazz); 1169 if (parcel != NULL) { 1170 const status_t err = parcel->writeDouble(val); 1171 if (err != NO_ERROR) { 1172 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1173 } 1174 } 1175} 1176 1177static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val) 1178{ 1179 Parcel* parcel = parcelForJavaObject(env, clazz); 1180 if (parcel != NULL) { 1181 status_t err = NO_MEMORY; 1182 if (val) { 1183 const jchar* str = env->GetStringCritical(val, 0); 1184 if (str) { 1185 err = parcel->writeString16(str, env->GetStringLength(val)); 1186 env->ReleaseStringCritical(val, str); 1187 } 1188 } else { 1189 err = parcel->writeString16(NULL, 0); 1190 } 1191 if (err != NO_ERROR) { 1192 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1193 } 1194 } 1195} 1196 1197static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object) 1198{ 1199 Parcel* parcel = parcelForJavaObject(env, clazz); 1200 if (parcel != NULL) { 1201 const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object)); 1202 if (err != NO_ERROR) { 1203 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1204 } 1205 } 1206} 1207 1208static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1209{ 1210 Parcel* parcel = parcelForJavaObject(env, clazz); 1211 if (parcel != NULL) { 1212 const status_t err = parcel->writeDupFileDescriptor( 1213 env->GetIntField(object, gFileDescriptorOffsets.mDescriptor)); 1214 if (err != NO_ERROR) { 1215 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1216 } 1217 } 1218} 1219 1220static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz) 1221{ 1222 jbyteArray ret = NULL; 1223 1224 Parcel* parcel = parcelForJavaObject(env, clazz); 1225 if (parcel != NULL) { 1226 int32_t len = parcel->readInt32(); 1227 1228 // sanity check the stored length against the true data size 1229 if (len >= 0 && len <= (int32_t)parcel->dataAvail()) { 1230 ret = env->NewByteArray(len); 1231 1232 if (ret != NULL) { 1233 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1234 if (a2) { 1235 const void* data = parcel->readInplace(len); 1236 memcpy(a2, data, len); 1237 env->ReleasePrimitiveArrayCritical(ret, a2, 0); 1238 } 1239 } 1240 } 1241 } 1242 1243 return ret; 1244} 1245 1246static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz) 1247{ 1248 Parcel* parcel = parcelForJavaObject(env, clazz); 1249 if (parcel != NULL) { 1250 return parcel->readInt32(); 1251 } 1252 return 0; 1253} 1254 1255static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz) 1256{ 1257 Parcel* parcel = parcelForJavaObject(env, clazz); 1258 if (parcel != NULL) { 1259 return parcel->readInt64(); 1260 } 1261 return 0; 1262} 1263 1264static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz) 1265{ 1266 Parcel* parcel = parcelForJavaObject(env, clazz); 1267 if (parcel != NULL) { 1268 return parcel->readFloat(); 1269 } 1270 return 0; 1271} 1272 1273static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz) 1274{ 1275 Parcel* parcel = parcelForJavaObject(env, clazz); 1276 if (parcel != NULL) { 1277 return parcel->readDouble(); 1278 } 1279 return 0; 1280} 1281 1282static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz) 1283{ 1284 Parcel* parcel = parcelForJavaObject(env, clazz); 1285 if (parcel != NULL) { 1286 size_t len; 1287 const char16_t* str = parcel->readString16Inplace(&len); 1288 if (str) { 1289 return env->NewString(str, len); 1290 } 1291 return NULL; 1292 } 1293 return NULL; 1294} 1295 1296static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz) 1297{ 1298 Parcel* parcel = parcelForJavaObject(env, clazz); 1299 if (parcel != NULL) { 1300 return javaObjectForIBinder(env, parcel->readStrongBinder()); 1301 } 1302 return NULL; 1303} 1304 1305static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz) 1306{ 1307 Parcel* parcel = parcelForJavaObject(env, clazz); 1308 if (parcel != NULL) { 1309 int fd = parcel->readFileDescriptor(); 1310 if (fd < 0) return NULL; 1311 fd = dup(fd); 1312 if (fd < 0) return NULL; 1313 jobject object = env->NewObject( 1314 gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); 1315 if (object != NULL) { 1316 //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd); 1317 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd); 1318 } 1319 return object; 1320 } 1321 return NULL; 1322} 1323 1324static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz, 1325 jstring name, jint mode) 1326{ 1327 if (name == NULL) { 1328 jniThrowException(env, "java/lang/NullPointerException", NULL); 1329 return NULL; 1330 } 1331 const jchar* str = env->GetStringCritical(name, 0); 1332 if (str == NULL) { 1333 // Whatever, whatever. 1334 jniThrowException(env, "java/lang/IllegalStateException", NULL); 1335 return NULL; 1336 } 1337 String8 name8(str, env->GetStringLength(name)); 1338 env->ReleaseStringCritical(name, str); 1339 int flags=0; 1340 switch (mode&0x30000000) { 1341 case 0: 1342 case 0x10000000: 1343 flags = O_RDONLY; 1344 break; 1345 case 0x20000000: 1346 flags = O_WRONLY; 1347 break; 1348 case 0x30000000: 1349 flags = O_RDWR; 1350 break; 1351 } 1352 1353 if (mode&0x08000000) flags |= O_CREAT; 1354 if (mode&0x04000000) flags |= O_TRUNC; 1355 if (mode&0x02000000) flags |= O_APPEND; 1356 1357 int realMode = S_IRWXU|S_IRWXG; 1358 if (mode&0x00000001) realMode |= S_IROTH; 1359 if (mode&0x00000002) realMode |= S_IWOTH; 1360 1361 int fd = open(name8.string(), flags, realMode); 1362 if (fd < 0) { 1363 jniThrowException(env, "java/io/FileNotFoundException", NULL); 1364 return NULL; 1365 } 1366 jobject object = newFileDescriptor(env, fd); 1367 if (object == NULL) { 1368 close(fd); 1369 } 1370 return object; 1371} 1372 1373static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object) 1374{ 1375 int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1376 if (fd >= 0) { 1377 env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1); 1378 //LOGI("Closing ParcelFileDescriptor %d\n", fd); 1379 close(fd); 1380 } 1381} 1382 1383static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz) 1384{ 1385 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1386 if (own) { 1387 Parcel* parcel = parcelForJavaObject(env, clazz); 1388 if (parcel != NULL) { 1389 //LOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel); 1390 parcel->freeData(); 1391 } 1392 } 1393} 1394 1395static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt) 1396{ 1397 Parcel* parcel = (Parcel*)parcelInt; 1398 int own = 0; 1399 if (!parcel) { 1400 //LOGI("Initializing obj %p: creating new Parcel\n", clazz); 1401 own = 1; 1402 parcel = new Parcel; 1403 } else { 1404 //LOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel); 1405 } 1406 if (parcel == NULL) { 1407 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 1408 return; 1409 } 1410 //LOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own); 1411 env->SetIntField(clazz, gParcelOffsets.mOwnObject, own); 1412 env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel); 1413} 1414 1415static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz) 1416{ 1417 int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject); 1418 if (own) { 1419 Parcel* parcel = parcelForJavaObject(env, clazz); 1420 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1421 //LOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel); 1422 delete parcel; 1423 } else { 1424 env->SetIntField(clazz, gParcelOffsets.mObject, 0); 1425 //LOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz); 1426 } 1427} 1428 1429static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz) 1430{ 1431 Parcel* parcel = parcelForJavaObject(env, clazz); 1432 if (parcel == NULL) { 1433 return NULL; 1434 } 1435 1436 // do not marshall if there are binder objects in the parcel 1437 if (parcel->objectsCount()) 1438 { 1439 jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects."); 1440 return NULL; 1441 } 1442 1443 jbyteArray ret = env->NewByteArray(parcel->dataSize()); 1444 1445 if (ret != NULL) 1446 { 1447 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0); 1448 if (array != NULL) 1449 { 1450 memcpy(array, parcel->data(), parcel->dataSize()); 1451 env->ReleasePrimitiveArrayCritical(ret, array, 0); 1452 } 1453 } 1454 1455 return ret; 1456} 1457 1458static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length) 1459{ 1460 Parcel* parcel = parcelForJavaObject(env, clazz); 1461 if (parcel == NULL || length < 0) { 1462 return; 1463 } 1464 1465 jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0); 1466 if (array) 1467 { 1468 parcel->setDataSize(length); 1469 parcel->setDataPosition(0); 1470 1471 void* raw = parcel->writeInplace(length); 1472 memcpy(raw, (array + offset), length); 1473 1474 env->ReleasePrimitiveArrayCritical(data, array, 0); 1475 } 1476} 1477 1478static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length) 1479{ 1480 Parcel* thisParcel = parcelForJavaObject(env, clazz); 1481 if (thisParcel == NULL) { 1482 return; 1483 } 1484 Parcel* otherParcel = parcelForJavaObject(env, parcel); 1485 if (otherParcel == NULL) { 1486 return; 1487 } 1488 1489 (void) thisParcel->appendFrom(otherParcel, offset, length); 1490} 1491 1492static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz) 1493{ 1494 jboolean ret = JNI_FALSE; 1495 Parcel* parcel = parcelForJavaObject(env, clazz); 1496 if (parcel != NULL) { 1497 if (parcel->hasFileDescriptors()) { 1498 ret = JNI_TRUE; 1499 } 1500 } 1501 return ret; 1502} 1503 1504static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name) 1505{ 1506 Parcel* parcel = parcelForJavaObject(env, clazz); 1507 if (parcel != NULL) { 1508 // In the current implementation, the token is just the serialized interface name that 1509 // the caller expects to be invoking 1510 const jchar* str = env->GetStringCritical(name, 0); 1511 if (str != NULL) { 1512 parcel->writeInterfaceToken(String16(str, env->GetStringLength(name))); 1513 env->ReleaseStringCritical(name, str); 1514 } 1515 } 1516} 1517 1518static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name) 1519{ 1520 jboolean ret = JNI_FALSE; 1521 1522 Parcel* parcel = parcelForJavaObject(env, clazz); 1523 if (parcel != NULL) { 1524 const jchar* str = env->GetStringCritical(name, 0); 1525 if (str) { 1526 bool isValid = parcel->enforceInterface(String16(str, env->GetStringLength(name))); 1527 env->ReleaseStringCritical(name, str); 1528 if (isValid) { 1529 return; // everything was correct -> return silently 1530 } 1531 } 1532 } 1533 1534 // all error conditions wind up here 1535 jniThrowException(env, "java/lang/SecurityException", 1536 "Binder invocation to an incorrect interface"); 1537} 1538 1539// ---------------------------------------------------------------------------- 1540 1541static const JNINativeMethod gParcelMethods[] = { 1542 {"dataSize", "()I", (void*)android_os_Parcel_dataSize}, 1543 {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail}, 1544 {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition}, 1545 {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity}, 1546 {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize}, 1547 {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition}, 1548 {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity}, 1549 {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative}, 1550 {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt}, 1551 {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong}, 1552 {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat}, 1553 {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble}, 1554 {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString}, 1555 {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder}, 1556 {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor}, 1557 {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray}, 1558 {"readInt", "()I", (void*)android_os_Parcel_readInt}, 1559 {"readLong", "()J", (void*)android_os_Parcel_readLong}, 1560 {"readFloat", "()F", (void*)android_os_Parcel_readFloat}, 1561 {"readDouble", "()D", (void*)android_os_Parcel_readDouble}, 1562 {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString}, 1563 {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder}, 1564 {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor}, 1565 {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor}, 1566 {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor}, 1567 {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer}, 1568 {"init", "(I)V", (void*)android_os_Parcel_init}, 1569 {"destroy", "()V", (void*)android_os_Parcel_destroy}, 1570 {"marshall", "()[B", (void*)android_os_Parcel_marshall}, 1571 {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall}, 1572 {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom}, 1573 {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors}, 1574 {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken}, 1575 {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface}, 1576}; 1577 1578const char* const kParcelPathName = "android/os/Parcel"; 1579 1580static int int_register_android_os_Parcel(JNIEnv* env) 1581{ 1582 jclass clazz; 1583 1584 clazz = env->FindClass("android/util/Log"); 1585 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.util.Log"); 1586 gLogOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1587 gLogOffsets.mLogE = env->GetStaticMethodID( 1588 clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I"); 1589 assert(gLogOffsets.mLogE); 1590 1591 clazz = env->FindClass("java/io/FileDescriptor"); 1592 LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); 1593 gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1594 gFileDescriptorOffsets.mConstructor 1595 = env->GetMethodID(clazz, "<init>", "()V"); 1596 gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); 1597 LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL, 1598 "Unable to find descriptor field in java.io.FileDescriptor"); 1599 1600 clazz = env->FindClass("android/os/ParcelFileDescriptor"); 1601 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 1602 gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); 1603 gParcelFileDescriptorOffsets.mConstructor 1604 = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); 1605 1606 clazz = env->FindClass(kParcelPathName); 1607 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel"); 1608 1609 gParcelOffsets.mObject 1610 = env->GetFieldID(clazz, "mObject", "I"); 1611 gParcelOffsets.mOwnObject 1612 = env->GetFieldID(clazz, "mOwnObject", "I"); 1613 1614 return AndroidRuntime::registerNativeMethods( 1615 env, kParcelPathName, 1616 gParcelMethods, NELEM(gParcelMethods)); 1617} 1618 1619int register_android_os_Binder(JNIEnv* env) 1620{ 1621 if (int_register_android_os_Binder(env) < 0) 1622 return -1; 1623 if (int_register_android_os_BinderInternal(env) < 0) 1624 return -1; 1625 if (int_register_android_os_BinderProxy(env) < 0) 1626 return -1; 1627 if (int_register_android_os_Parcel(env) < 0) 1628 return -1; 1629 return 0; 1630} 1631 1632namespace android { 1633 1634// Returns the Unix file descriptor for a ParcelFileDescriptor object 1635int getParcelFileDescriptorFD(JNIEnv* env, jobject object) 1636{ 1637 return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor); 1638} 1639 1640} 1641