/* * * Copyright 2019, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include using teeui::localization::getLanguages; /* * JTypeTraits provides hints for JArray on how to access and free the array elements and how * to get the array size. The traits allow JArray to be used with jbyteArray, jintArray, * and jstring. */ template struct JTypeTraits; template <> struct JTypeTraits { using element_type = jint; using array_type = jintArray; static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) = &JNIEnv::GetIntArrayElements; static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*, jint) = &JNIEnv::ReleaseIntArrayElements; static constexpr jsize (JNIEnv::*const getArrayLength)(jarray) = &JNIEnv::GetArrayLength; }; template <> struct JTypeTraits { using element_type = jbyte; using array_type = jbyteArray; static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) = &JNIEnv::GetByteArrayElements; static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*, jint) = &JNIEnv::ReleaseByteArrayElements; static constexpr jsize (JNIEnv::*const getArrayLength)(jarray) = &JNIEnv::GetArrayLength; }; template <> struct JTypeTraits { using element_type = const char; using array_type = jstring; static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) = &JNIEnv::GetStringUTFChars; static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*) = &JNIEnv::ReleaseStringUTFChars; static constexpr jsize (JNIEnv::*const getArrayLength)(array_type) = &JNIEnv::GetStringUTFLength; }; /* * JArray can wrap various types of primitive Java arrays through a common typical C++ interface. * It tracks ownership. It can only be moved but not copied. It provides iterators through begin() * and end() so that it can be used in range for loops. */ template class JArray { private: JNIEnv* env_; using element_type = typename JTypeTraits::element_type; using array_type = typename JTypeTraits::array_type; array_type jarray_; element_type* buffer_; public: JArray(JNIEnv* env, array_type jarray) : env_(env), jarray_(jarray), buffer_(nullptr) { if (env_ == nullptr) return; buffer_ = (env_->*JTypeTraits::getArrayElements)(jarray, nullptr); } JArray(const JArray&) = delete; JArray(JArray&& rhs) : env_(rhs.env_), jarray_(rhs.jarray_), buffer_(rhs.buffer_) { rhs.env_ = nullptr; rhs.buffer_ = nullptr; } ~JArray(); JArray& operator=(const JArray&) = delete; JArray& operator=(JArray&& rhs) { if (&rhs != this) { env_ = rhs.env_; jarray_ = rhs.jarray_; buffer_ = rhs.buffer_; rhs.env_ = nullptr; rhs.buffer_ = nullptr; } return *this; } operator bool() const { return buffer_ != nullptr; } const jint& operator[](size_t offset) const { return buffer_[offset]; } element_type& operator[](size_t offset) { return buffer_[offset]; } size_t size() const { return (env_->*JTypeTraits::getArrayLength)(jarray_); } element_type* begin() { return buffer_; } element_type* end() { return buffer_ + size(); } const element_type* begin() const { return buffer_; } const element_type* end() const { return buffer_ + size(); } }; template JArray::~JArray() { if (env_ == nullptr) return; if (buffer_ == nullptr) return; (env_->*JTypeTraits::releaseArrayElements)(jarray_, buffer_, 0); } template <> JArray::~JArray() { if (env_ == nullptr) return; if (buffer_ == nullptr) return; (env_->*JTypeTraits::releaseArrayElements)(jarray_, buffer_); } using JIntArray = JArray; using JByteArray = JArray; using JString = JArray; static std::unique_ptr sCurrentExample; /* * Class: com_android_framebufferizer_NativeRenderer * Method: setDeviceInfo * Signature: (Lcom/android/framebufferizer/utils/DeviceInfo;ZZLjava/lang/String;)I */ extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_setDeviceInfo( JNIEnv* env, jclass, jobject jDeviceInfo, jboolean magnified, jboolean inverted, jstring layout_type) { JString layout(env, layout_type); using namespace teeui::example; jclass cDeviceInfo = env->FindClass("Lcom/android/framebufferizer/utils/DeviceInfo;"); jmethodID method = env->GetMethodID(cDeviceInfo, "getWidthPx", "()I"); DeviceInfo device_info; device_info.width_ = env->CallIntMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getHeightPx", "()I"); device_info.height_ = env->CallIntMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getDp2px", "()D"); device_info.dp2px_ = env->CallDoubleMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getMm2px", "()D"); device_info.mm2px_ = env->CallDoubleMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getPowerButtonTopMm", "()D"); device_info.powerButtonTopMm_ = env->CallDoubleMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getPowerButtonBottomMm", "()D"); device_info.powerButtonBottomMm_ = env->CallDoubleMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getVolUpButtonTopMm", "()D"); device_info.volUpButtonTopMm_ = env->CallDoubleMethod(jDeviceInfo, method); method = env->GetMethodID(cDeviceInfo, "getVolUpButtonBottomMm", "()D"); device_info.volUpButtonBottomMm_ = env->CallDoubleMethod(jDeviceInfo, method); sCurrentExample = createExample((strcmp(layout.begin(), kTouchButtonLayout) == 0) ? Examples::TouchButton : Examples::PhysButton); return sCurrentExample->setDeviceInfo(device_info, magnified, inverted); } /* * Class: com_android_framebufferizer_NativeRenderer * Method: renderBuffer * Signature: (IIIII[I)I */ extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_renderBuffer( JNIEnv* env, jclass, jint x, jint y, jint width, jint height, jint lineStride, jintArray jbuffer) { JIntArray buffer(env, jbuffer); using namespace teeui::example; if (!buffer) return kFrameBufferError; if (!sCurrentExample) return kLayoutExampleError; return sCurrentExample->renderUIIntoBuffer((uint32_t)x, (uint32_t)y, (uint32_t)width, (uint32_t)height, (uint32_t)lineStride, (uint32_t*)buffer.begin(), buffer.size()); } /* * Class: com_android_confirmationui_Translation_selectLangID * Method: selectLangID * Signature: (Ljava/lang/String;)V */ extern "C" JNIEXPORT void JNICALL Java_com_android_framebufferizer_NativeRenderer_setLanguage(JNIEnv* env, jclass, jstring jlang_id) { JString lang_id(env, jlang_id); if (sCurrentExample) sCurrentExample->selectLanguage(lang_id.begin()); } /* * Class: com_android_confirmationui_Translation_selectLangID * Method: selectLangID * Signature: ()[Ljava/lang/String; */ extern "C" JNIEXPORT jobjectArray JNICALL Java_com_android_framebufferizer_NativeRenderer_getLanguageIdList(JNIEnv* env, jclass) { jobjectArray language_ids; teeui::localization::Languages lang_list = getLanguages(); const char* const* native_data = lang_list.list; size_t list_size = lang_list.size; language_ids = (jobjectArray)env->NewObjectArray(list_size, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (size_t i = 0; i < list_size; i++) env->SetObjectArrayElement(language_ids, i, env->NewStringUTF(native_data[i])); return language_ids; } /* * Class: com_android_framebufferizer_NativeRenderer * Method: getAvailableLayouts * Signature: ()[Ljava/lang/String; */ extern "C" JNIEXPORT jobjectArray JNICALL Java_com_android_framebufferizer_NativeRenderer_getAvailableLayouts(JNIEnv* env, jclass) { using namespace teeui::example; jobjectArray available_layouts; const char* const* native_data = kAvailableLayouts; size_t list_size = NUM_LAYOUTS; available_layouts = (jobjectArray)env->NewObjectArray( list_size, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (size_t i = 0; i < list_size; i++) env->SetObjectArrayElement(available_layouts, i, env->NewStringUTF(native_data[i])); return available_layouts; } /* * Class: com_android_framebufferizer_NativeRenderer * Method: setConfimationMessage * Signature: (Ljava/lang/String;)V */ extern "C" JNIEXPORT void JNICALL Java_com_android_framebufferizer_NativeRenderer_setConfimationMessage( JNIEnv* env, jclass, jstring jConfirmationMessage) { JString confirmationMessage(env, jConfirmationMessage); if (sCurrentExample) sCurrentExample->setConfirmationMessage(confirmationMessage.begin()); } /* * Class: com_android_framebufferizer_NativeRenderer * Method: onEvent * Signature: (III)I */ extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_onEvent( JNIEnv*, jclass, jint x, jint y, jint event) { if (sCurrentExample) { return (jint)sCurrentExample->onEvent((uint32_t)x, (uint32_t)y, (uint32_t)event); } return 0; }