static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, jobject recipient, jint flags) // throws RemoteException { if (recipient == NULL) { jniThrowNullPointerException(env, NULL); return; } IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); assert(false); } LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { DeathRecipientList* list = (DeathRecipientList*) env->GetLongField(obj, gBinderProxyOffsets.mOrgue); sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list); status_t err = target->linkToDeath(jdr, NULL, flags); if (err != NO_ERROR) { // Failure adding the death recipient, so clear its reference // now. jdr->clearReference(); signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); } } }
wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle) { wp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { // We need to create a new BpBinder if there isn't currently one, OR we // are unable to acquire a weak reference on this current one. The // attemptIncWeak() is safe because we know the BpBinder destructor will always // call expungeHandle(), which acquires the same lock we are holding now. // We need to do this because there is a race condition between someone // releasing a reference on this BpBinder, and a new reference on its handle // arriving from the driver. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle); result = b; e->binder = b; if (b) e->refs = b->getWeakRefs(); } else { result = b; e->refs->decWeak(this); } } return result; }
static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, jobject recipient, jint flags) // throws RemoteException { if (recipient == NULL) { jniThrowNullPointerException(env, NULL); return; } BinderProxyNativeData *nd = getBPNativeData(env, obj); IBinder* target = nd->mObject.get(); LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { DeathRecipientList* list = nd->mOrgue.get(); sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient, list); status_t err = target->linkToDeath(jdr, NULL, flags); if (err != NO_ERROR) { // Failure adding the death recipient, so clear its reference // now. jdr->clearReference(); signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); } } }
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle) { sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { // We need to create a new BpBinder if there isn't currently one, OR we // are unable to acquire a weak reference on this current one. See comment // in getWeakProxyForHandle() for more info about this. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } else { // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn't have one // but another team is sending the handle to us. result.force_set(b); e->refs->decWeak(this); } } return result; }
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj, jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException { if (dataObj == NULL) { jniThrowNullPointerException(env, NULL); return JNI_FALSE; } Parcel* data = parcelForJavaObject(env, dataObj); if (data == NULL) { return JNI_FALSE; } Parcel* reply = parcelForJavaObject(env, replyObj); if (reply == NULL && replyObj != NULL) { return JNI_FALSE; } IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!"); return JNI_FALSE; } ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n", target, obj, code); bool time_binder_calls; int64_t start_millis; if (kEnableBinderSample) { // Only log the binder call duration for things on the Java-level main thread. // But if we don't time_binder_calls = should_time_binder_calls(); if (time_binder_calls) { start_millis = uptimeMillis(); } } //printf("Transact from Java code to %p sending: ", target); data->print(); status_t err = target->transact(code, *data, reply, flags); //if (reply) printf("Transact from Java code to %p received: ", target); reply->print(); if (kEnableBinderSample) { if (time_binder_calls) { conditionally_log_binder_call(start_millis, target, code); } } if (err == NO_ERROR) { return JNI_TRUE; } else if (err == UNKNOWN_TRANSACTION) { return JNI_FALSE; } signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/); return JNI_FALSE; }
static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) { IBinder* target = getBPNativeData(env, obj)->mObject.get(); if (target == NULL) { return JNI_FALSE; } bool alive = target->isBinderAlive(); return alive ? JNI_TRUE : JNI_FALSE; }
static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) { IBinder* target = getBPNativeData(env, obj)->mObject.get(); if (target == NULL) { return JNI_FALSE; } status_t err = target->pingBinder(); return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; }
static jboolean android_os_BinderProxy_isBinderAlive(JNIEnv* env, jobject obj) { IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { return JNI_FALSE; } bool alive = target->isBinderAlive(); return alive ? JNI_TRUE : JNI_FALSE; }
static jboolean android_os_BinderProxy_pingBinder(JNIEnv* env, jobject obj) { IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { return JNI_FALSE; } status_t err = target->pingBinder(); return err == NO_ERROR ? JNI_TRUE : JNI_FALSE; }
static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) { IBinder* target = (IBinder*) env->GetIntField(obj, gBinderProxyOffsets.mObject); if (target != NULL) { const String16& desc = target->getInterfaceDescriptor(); return env->NewString((jchar*)desc.string(), desc.size()); } jniThrowException(env, "java/lang/RuntimeException", "No binder found for object"); return NULL; }
static jstring android_os_BinderProxy_getInterfaceDescriptor(JNIEnv* env, jobject obj) { IBinder* target = getBPNativeData(env, obj)->mObject.get(); if (target != NULL) { const String16& desc = target->getInterfaceDescriptor(); return env->NewString(reinterpret_cast<const jchar*>(desc.string()), desc.size()); } jniThrowException(env, "java/lang/RuntimeException", "No binder found for object"); return NULL; }
static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) { IBinder* b = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); DeathRecipientList* drl = (DeathRecipientList*) env->GetLongField(obj, gBinderProxyOffsets.mOrgue); LOGDEATH("Destroying BinderProxy %p: binder=%p drl=%p\n", obj, b, drl); env->SetLongField(obj, gBinderProxyOffsets.mObject, 0); env->SetLongField(obj, gBinderProxyOffsets.mOrgue, 0); drl->decStrong((void*)javaObjectForIBinder); b->decStrong((void*)javaObjectForIBinder); IPCThreadState::self()->flushCommands(); }
static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, jobject recipient, jint flags) { jboolean res = JNI_FALSE; if (recipient == NULL) { jniThrowNullPointerException(env, NULL); return res; } IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); if (target == NULL) { ALOGW("Binder has been finalized when calling linkToDeath() with recip=%p)\n", recipient); return JNI_FALSE; } LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { status_t err = NAME_NOT_FOUND; // If we find the matching recipient, proceed to unlink using that DeathRecipientList* list = (DeathRecipientList*) env->GetLongField(obj, gBinderProxyOffsets.mOrgue); sp<JavaDeathRecipient> origJDR = list->find(recipient); LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get()); if (origJDR != NULL) { wp<IBinder::DeathRecipient> dr; err = target->unlinkToDeath(origJDR, NULL, flags, &dr); if (err == NO_ERROR && dr != NULL) { sp<IBinder::DeathRecipient> sdr = dr.promote(); JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); if (jdr != NULL) { jdr->clearReference(); } } } if (err == NO_ERROR || err == DEAD_OBJECT) { res = JNI_TRUE; } else { jniThrowException(env, "java/util/NoSuchElementException", "Death link does not exist"); } } return res; }
void flatten_binder(const wptr<IBinder>& binder, flat_binder_object* out) { out->length = sizeof(flat_binder_object) - sizeof(small_flat_data); if (binder != NULL) { sptr<IBinder> real = binder.promote(); if (real != NULL) { IBinder *local = real->LocalBinder(); if (!local) { BpBinder *proxy = real->RemoteBinder(); ErrFatalErrorIf(!proxy, "Binder is neither local nor remote"); const int32_t handle = proxy->Handle(); out->type = kPackedLargeBinderWeakHandleType; out->handle = handle; } else { out->type = kPackedLargeBinderWeakType; out->binder = binder.get_weak_atom_ptr()->cookie; out->cookie = binder.get_weak_atom_ptr()->atom; } } else { // This is bad! In order to build a SValue from a binder, // we need to probe it for information, which requires a primary // reference... but we don't have one. As something of a hack, // we will do a direct dynamic_cast<> on the binder, since we // know an BpBinder doesn't get destroyed until all weak references // are removed. SAtom::weak_atom_ptr* weak = binder.get_weak_atom_ptr(); IBinder* local = static_cast<IBinder*>(weak->cookie); BpBinder* proxy = local->RemoteBinder(); if (proxy != NULL) { // Found a proxy, so use it. const int32_t handle = proxy->Handle(); out->type = kPackedLargeBinderWeakHandleType; out->handle = handle; } else { // Couldn't cast as a proxy, so assume this is a local binder. out->type = kPackedLargeBinderWeakType; out->binder = weak->cookie; out->cookie = weak->atom; } } } else { out->type = kPackedLargeBinderType; out->binder = NULL; } }
AutoPtr<DisplayDevice> VirtualDisplayAdapter::CreateVirtualDisplayLocked( /* [in] */ IIVirtualDisplayCallback* callback, /* [in] */ IIMediaProjection* projection, /* [in] */ Int32 ownerUid, /* [in] */ const String& ownerPackageName, /* [in] */ const String& name, /* [in] */ Int32 width, /* [in] */ Int32 height, /* [in] */ Int32 densityDpi, /* [in] */ ISurface* surface, /* [in] */ Int32 flags) { AutoPtr<ISurfaceControlHelper> helper; CSurfaceControlHelper::AcquireSingleton((ISurfaceControlHelper**)&helper); Boolean secure = (flags & IDisplayManager::VIRTUAL_DISPLAY_FLAG_SECURE) != 0; IBinder* appToken = IBinder::Probe(callback); AutoPtr<IBinder> displayToken; helper->CreateDisplay(name, secure, (IBinder**)&displayToken); AutoPtr<Callback> cb = new Callback(callback, mHandler, this); AutoPtr<VirtualDisplayDevice> device = new VirtualDisplayDevice( displayToken, appToken, ownerUid, ownerPackageName, name, width, height, densityDpi, surface, flags, cb, this); mVirtualDisplayDevices->Put(TO_IINTERFACE(appToken), TO_IINTERFACE(device)); // try { AutoPtr<IProxy> proxy = (IProxy*)appToken->Probe(EIID_IProxy); ECode ec = NOERROR; if (projection != NULL) { AutoPtr<IIMediaProjectionCallback> mpcb; assert(0 && "TODO"); // CMediaProjectionCallback::New(appToken, IObject::Probe(this), // (IIMediaProjectionCallback**)&mpcb); ec = projection->RegisterCallback(mpcb); FAIL_GOTO(ec, _EXIT_) }
/****************************************************************************** * frameworks/base/media/mediaserver/main_mediaserver.cpp * * Library: * LOCAL_MODULE:= mediaserver * * system/core/rootdir/init.rc * * service media /system/bin/mediaserver user media group system audio camera graphics inet net_bt net_bt_admin * */ int main(int argc, char** argv) { // Get IServiceManager sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); AudioFlinger::instantiate(); // void AudioFlinger::instantiate() { // AudioFlinger <-- BnAudioFlinger <-- BnInterface<IAudioFlinger> <-- // BBinder <-- IBinder <-- RefBase defaultServiceManager()->addService(String16("media.audio_flinger"), new AudioFlinger()); // status_t BpServiceManager::addService(const String16& name, const // sp<IBinder>& service) // // The service is IAudioFlinger as BBinder and IBinder interface. { Parcel data, reply; // write to IServiceManager data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); // write name "android.media.IAudioFlinger" data.writeString16(name); data.writeStrongBinder(service); // status_t Parcel::writeStrongBinder(const sp<IBinder>& val) { flatten_binder(ProcessState::self(), val, this); // status_t flatten_binder(const sp<ProcessState>& proc, const // sp<IBinder>& binder, Parcel* out) { flat_binder_object obj; IBinder *local = binder->localBinder(); // BBinder* BBinder::localBinder() // // AudioFlinger is derived from BBinder, so it shall call // BBinder::localBinder() to return itself // // TODO: check if the pointer will be switched to handle in // binder driver { return this; } obj.type = BINDER_TYPE_BINDER; obj.binder = local->getWeakRefs(); obj.cookie = local; finish_flatten_binder(binder, obj, out); // inline static status_t finish_flatten_binder(const // sp<IBinder>& binder, const flat_binder_object& flat, // Parcel* out) { out->writeObject(flat, false); } // After the packet for addService RPC call is made, // BpServiceManager::addService will call BpBinder’s // transact. // } } // writeStrongBinder() } } MediaPlayerService::instantiate(); // void MediaPlayerService::instantiate() // frameworks/base/media/libmediaplayerservice/MediaPlayerService.cpp // TODO: how to connect the pointer to the handle?? { defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService()); } }