static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { ALOGE("An exception was thrown by callback '%s'.", methodName); LOGE_EX(env); env->ExceptionClear(); return true; } return false; }
static inline void CheckExceptions(JNIEnv* env, const char* methodName) { if(!env->ExceptionCheck()) { return; } ALOGE("An exception was thrown by '%s'.", methodName); LOGE_EX(env); env->ExceptionClear(); }
jobject android_hardware_HardwareBuffer_createFromAHardwareBuffer( JNIEnv* env, AHardwareBuffer* hardwareBuffer) { GraphicBuffer* buffer = AHardwareBuffer_to_GraphicBuffer(hardwareBuffer); GraphicBufferWrapper* wrapper = new GraphicBufferWrapper(buffer); jobject hardwareBufferObj = env->NewObject(gHardwareBufferClassInfo.clazz, gHardwareBufferClassInfo.ctor, reinterpret_cast<jlong>(wrapper)); if (hardwareBufferObj == NULL) { delete wrapper; if (env->ExceptionCheck()) { ALOGE("Could not create instance of HardwareBuffer from AHardwareBuffer."); LOGE_EX(env); env->ExceptionClear(); } return nullptr; } return hardwareBufferObj; }
jobject android_view_MotionEvent_obtainAsCopy(JNIEnv* env, const MotionEvent* event) { jobject eventObj = env->CallStaticObjectMethod(gMotionEventClassInfo.clazz, gMotionEventClassInfo.obtain); if (env->ExceptionCheck() || !eventObj) { ALOGE("An exception occurred while obtaining a motion event."); LOGE_EX(env); env->ExceptionClear(); return NULL; } MotionEvent* destEvent = android_view_MotionEvent_getNativePtr(env, eventObj); if (!destEvent) { destEvent = new MotionEvent(); android_view_MotionEvent_setNativePtr(env, eventObj, destEvent); } destEvent->copyFrom(event, true); return eventObj; }
// Called each time a custom function is evaluated. static void sqliteCustomFunctionCallback(sqlite3_context *context, int argc, sqlite3_value **argv) { JNIEnv* env = AndroidRuntime::getJNIEnv(); // Get the callback function object. // Create a new local reference to it in case the callback tries to do something // dumb like unregister the function (thereby destroying the global ref) while it is running. jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context)); jobject functionObj = env->NewLocalRef(functionObjGlobal); jobjectArray argsArray = env->NewObjectArray(argc, gStringClassInfo.clazz, NULL); if (argsArray) { for (int i = 0; i < argc; i++) { const jchar* arg = static_cast<const jchar*>(sqlite3_value_text16(argv[i])); if (!arg) { ALOGW("NULL argument in custom_function_callback. This should not happen."); } else { size_t argLen = sqlite3_value_bytes16(argv[i]) / sizeof(jchar); jstring argStr = env->NewString(arg, argLen); if (!argStr) { goto error; // out of memory error } env->SetObjectArrayElement(argsArray, i, argStr); env->DeleteLocalRef(argStr); } } // TODO: Support functions that return values. env->CallVoidMethod(functionObj, gSQLiteCustomFunctionClassInfo.dispatchCallback, argsArray); error: env->DeleteLocalRef(argsArray); } env->DeleteLocalRef(functionObj); if (env->ExceptionCheck()) { ALOGE("An exception was thrown by custom SQLite function."); LOGE_EX(env); env->ExceptionClear(); } }
jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) { jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain, nanoseconds_to_milliseconds(event->getDownTime()), nanoseconds_to_milliseconds(event->getEventTime()), event->getAction(), event->getKeyCode(), event->getRepeatCount(), event->getMetaState(), event->getDeviceId(), event->getScanCode(), event->getFlags(), event->getSource(), NULL); if (env->ExceptionCheck()) { LOGE("An exception occurred while obtaining a key event."); LOGE_EX(env); env->ExceptionClear(); return NULL; } return eventObj; }
jobject android_view_Surface_createFromIGraphicBufferProducer(JNIEnv* env, const sp<IGraphicBufferProducer>& bufferProducer) { if (bufferProducer == NULL) { return NULL; } sp<Surface> surface(new Surface(bufferProducer, true)); if (surface == NULL) { return NULL; } jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get()); if (surfaceObj == NULL) { if (env->ExceptionCheck()) { ALOGE("Could not create instance of Surface from IGraphicBufferProducer."); LOGE_EX(env); env->ExceptionClear(); } return NULL; } surface->incStrong(&sRefBaseOwner); return surfaceObj; }
static void custom_function_callback(sqlite3_context * context, int argc, sqlite3_value ** argv) { JNIEnv* env = AndroidRuntime::getJNIEnv(); if (!env) { LOGE("custom_function_callback cannot call into Java on this thread"); return; } // get global ref to CustomFunction object from our user data jobject function = (jobject)sqlite3_user_data(context); // pack up the arguments into a string array jobjectArray strArray = env->NewObjectArray(argc, string_class, NULL); if (!strArray) goto done; for (int i = 0; i < argc; i++) { char* arg = (char *)sqlite3_value_text(argv[i]); if (!arg) { LOGE("NULL argument in custom_function_callback. This should not happen."); return; } jobject obj = env->NewStringUTF(arg); if (!obj) goto done; env->SetObjectArrayElement(strArray, i, obj); env->DeleteLocalRef(obj); } env->CallVoidMethod(function, method_custom_function_callback, strArray); env->DeleteLocalRef(strArray); done: if (env->ExceptionCheck()) { LOGE("An exception was thrown by custom sqlite3 function."); LOGE_EX(env); env->ExceptionClear(); } }
int NativeInputQueue::handleReceiveCallback(int receiveFd, int events, void* data) { NativeInputQueue* q = static_cast<NativeInputQueue*>(data); JNIEnv* env = AndroidRuntime::getJNIEnv(); sp<Connection> connection; InputEvent* inputEvent; jobject inputHandlerObjLocal; jlong finishedToken; { // acquire lock AutoMutex _l(q->mLock); ssize_t connectionIndex = q->mConnectionsByReceiveFd.indexOfKey(receiveFd); if (connectionIndex < 0) { ALOGE("Received spurious receive callback for unknown input channel. " "fd=%d, events=0x%x", receiveFd, events); return 0; // remove the callback } connection = q->mConnectionsByReceiveFd.valueAt(connectionIndex); if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred. " "events=0x%x", connection->getInputChannelName(), events); return 0; // remove the callback } if (! (events & ALOOPER_EVENT_INPUT)) { ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. " "events=0x%x", connection->getInputChannelName(), events); return 1; } status_t status = connection->inputConsumer.receiveDispatchSignal(); if (status) { ALOGE("channel '%s' ~ Failed to receive dispatch signal. status=%d", connection->getInputChannelName(), status); return 0; // remove the callback } if (connection->messageInProgress) { ALOGW("channel '%s' ~ Publisher sent spurious dispatch signal.", connection->getInputChannelName()); return 1; } status = connection->inputConsumer.consume(& connection->inputEventFactory, & inputEvent); if (status) { ALOGW("channel '%s' ~ Failed to consume input event. status=%d", connection->getInputChannelName(), status); connection->inputConsumer.sendFinishedSignal(false); return 1; } connection->messageInProgress = true; connection->messageSeqNum += 1; finishedToken = generateFinishedToken(receiveFd, connection->id, connection->messageSeqNum); inputHandlerObjLocal = env->NewLocalRef(connection->inputHandlerObjGlobal); } // release lock // Invoke the handler outside of the lock. // // Note: inputEvent is stored in a field of the connection object which could potentially // become disposed due to the input channel being unregistered concurrently. // For this reason, we explicitly keep the connection object alive by holding // a strong pointer to it within this scope. We also grabbed a local reference to // the input handler object itself for the same reason. int32_t inputEventType = inputEvent->getType(); jobject inputEventObj; jmethodID dispatchMethodId; switch (inputEventType) { case AINPUT_EVENT_TYPE_KEY: #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ Received key event.", connection->getInputChannelName()); #endif inputEventObj = android_view_KeyEvent_fromNative(env, static_cast<KeyEvent*>(inputEvent)); dispatchMethodId = gInputQueueClassInfo.dispatchKeyEvent; break; case AINPUT_EVENT_TYPE_MOTION: #if DEBUG_DISPATCH_CYCLE ALOGD("channel '%s' ~ Received motion event.", connection->getInputChannelName()); #endif inputEventObj = android_view_MotionEvent_obtainAsCopy(env, static_cast<MotionEvent*>(inputEvent)); dispatchMethodId = gInputQueueClassInfo.dispatchMotionEvent; break; default: assert(false); // InputConsumer should prevent this from ever happening inputEventObj = NULL; } if (! inputEventObj) { ALOGW("channel '%s' ~ Failed to obtain DVM event object.", connection->getInputChannelName()); env->DeleteLocalRef(inputHandlerObjLocal); q->finished(env, finishedToken, false, false); return 1; } #if DEBUG_DISPATCH_CYCLE ALOGD("Invoking input handler."); #endif env->CallStaticVoidMethod(gInputQueueClassInfo.clazz, dispatchMethodId, inputHandlerObjLocal, inputEventObj, jlong(finishedToken)); #if DEBUG_DISPATCH_CYCLE ALOGD("Returned from input handler."); #endif if (env->ExceptionCheck()) { ALOGE("An exception occurred while invoking the input handler for an event."); LOGE_EX(env); env->ExceptionClear(); q->finished(env, finishedToken, false, true /*ignoreSpuriousFinish*/); } env->DeleteLocalRef(inputEventObj); env->DeleteLocalRef(inputHandlerObjLocal); return 1; }