1 /*
2  *
3  * Copyright 2019, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <jni.h>
19 #include <teeui/example/example.h>
20 #include <teeui/localization/ConfirmationUITranslations.h>
21 
22 using teeui::localization::getLanguages;
23 /*
24  * JTypeTraits provides hints for JArray on how to access and free the array elements and how
25  * to get the array size. The traits allow JArray to be used with jbyteArray, jintArray,
26  * and jstring.
27  */
28 template <typename T> struct JTypeTraits;
29 
30 template <> struct JTypeTraits<jintArray> {
31     using element_type = jint;
32     using array_type = jintArray;
33 
34     static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) =
35         &JNIEnv::GetIntArrayElements;
36     static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*, jint) =
37         &JNIEnv::ReleaseIntArrayElements;
38     static constexpr jsize (JNIEnv::*const getArrayLength)(jarray) = &JNIEnv::GetArrayLength;
39 };
40 
41 template <> struct JTypeTraits<jbyteArray> {
42     using element_type = jbyte;
43     using array_type = jbyteArray;
44 
45     static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) =
46         &JNIEnv::GetByteArrayElements;
47     static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*, jint) =
48         &JNIEnv::ReleaseByteArrayElements;
49     static constexpr jsize (JNIEnv::*const getArrayLength)(jarray) = &JNIEnv::GetArrayLength;
50 };
51 
52 template <> struct JTypeTraits<jstring> {
53     using element_type = const char;
54     using array_type = jstring;
55 
56     static constexpr element_type* (JNIEnv::*const getArrayElements)(array_type, jboolean*) =
57         &JNIEnv::GetStringUTFChars;
58     static constexpr void (JNIEnv::*const releaseArrayElements)(array_type, element_type*) =
59         &JNIEnv::ReleaseStringUTFChars;
60     static constexpr jsize (JNIEnv::*const getArrayLength)(array_type) =
61         &JNIEnv::GetStringUTFLength;
62 };
63 
64 /*
65  * JArray can wrap various types of primitive Java arrays through a common typical C++ interface.
66  * It tracks ownership. It can only be moved but not copied. It provides iterators through begin()
67  * and end() so that it can be used in range for loops.
68  */
69 template <typename T> class JArray {
70   private:
71     JNIEnv* env_;
72     using element_type = typename JTypeTraits<T>::element_type;
73     using array_type = typename JTypeTraits<T>::array_type;
74     array_type jarray_;
75     element_type* buffer_;
76 
77   public:
JArray(JNIEnv * env,array_type jarray)78     JArray(JNIEnv* env, array_type jarray) : env_(env), jarray_(jarray), buffer_(nullptr) {
79         if (env_ == nullptr) return;
80         buffer_ = (env_->*JTypeTraits<T>::getArrayElements)(jarray, nullptr);
81     }
82     JArray(const JArray&) = delete;
JArray(JArray && rhs)83     JArray(JArray&& rhs) : env_(rhs.env_), jarray_(rhs.jarray_), buffer_(rhs.buffer_) {
84         rhs.env_ = nullptr;
85         rhs.buffer_ = nullptr;
86     }
87     ~JArray();
88 
89     JArray& operator=(const JArray&) = delete;
operator =(JArray && rhs)90     JArray& operator=(JArray&& rhs) {
91         if (&rhs != this) {
92             env_ = rhs.env_;
93             jarray_ = rhs.jarray_;
94             buffer_ = rhs.buffer_;
95             rhs.env_ = nullptr;
96             rhs.buffer_ = nullptr;
97         }
98         return *this;
99     }
100 
operator bool() const101     operator bool() const { return buffer_ != nullptr; }
operator [](size_t offset) const102     const jint& operator[](size_t offset) const { return buffer_[offset]; }
operator [](size_t offset)103     element_type& operator[](size_t offset) { return buffer_[offset]; }
size() const104     size_t size() const { return (env_->*JTypeTraits<T>::getArrayLength)(jarray_); }
begin()105     element_type* begin() { return buffer_; }
end()106     element_type* end() { return buffer_ + size(); }
begin() const107     const element_type* begin() const { return buffer_; }
end() const108     const element_type* end() const { return buffer_ + size(); }
109 };
110 
~JArray()111 template <typename T> JArray<T>::~JArray() {
112     if (env_ == nullptr) return;
113     if (buffer_ == nullptr) return;
114     (env_->*JTypeTraits<T>::releaseArrayElements)(jarray_, buffer_, 0);
115 }
116 
~JArray()117 template <> JArray<jstring>::~JArray() {
118     if (env_ == nullptr) return;
119     if (buffer_ == nullptr) return;
120     (env_->*JTypeTraits<jstring>::releaseArrayElements)(jarray_, buffer_);
121 }
122 
123 using JIntArray = JArray<jintArray>;
124 using JByteArray = JArray<jbyteArray>;
125 using JString = JArray<jstring>;
126 
127 static std::unique_ptr<teeui::example::ITeeuiExample> sCurrentExample;
128 
129 /*
130  * Class:     com_android_framebufferizer_NativeRenderer
131  * Method:    setDeviceInfo
132  * Signature: (Lcom/android/framebufferizer/utils/DeviceInfo;ZZLjava/lang/String;)I
133  */
Java_com_android_framebufferizer_NativeRenderer_setDeviceInfo(JNIEnv * env,jclass,jobject jDeviceInfo,jboolean magnified,jboolean inverted,jstring layout_type)134 extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_setDeviceInfo(
135     JNIEnv* env, jclass, jobject jDeviceInfo, jboolean magnified, jboolean inverted,
136     jstring layout_type) {
137     JString layout(env, layout_type);
138     using namespace teeui::example;
139     jclass cDeviceInfo = env->FindClass("Lcom/android/framebufferizer/utils/DeviceInfo;");
140     jmethodID method = env->GetMethodID(cDeviceInfo, "getWidthPx", "()I");
141     DeviceInfo device_info;
142     device_info.width_ = env->CallIntMethod(jDeviceInfo, method);
143     method = env->GetMethodID(cDeviceInfo, "getHeightPx", "()I");
144     device_info.height_ = env->CallIntMethod(jDeviceInfo, method);
145     method = env->GetMethodID(cDeviceInfo, "getDp2px", "()D");
146     device_info.dp2px_ = env->CallDoubleMethod(jDeviceInfo, method);
147     method = env->GetMethodID(cDeviceInfo, "getMm2px", "()D");
148     device_info.mm2px_ = env->CallDoubleMethod(jDeviceInfo, method);
149     method = env->GetMethodID(cDeviceInfo, "getPowerButtonTopMm", "()D");
150     device_info.powerButtonTopMm_ = env->CallDoubleMethod(jDeviceInfo, method);
151     method = env->GetMethodID(cDeviceInfo, "getPowerButtonBottomMm", "()D");
152     device_info.powerButtonBottomMm_ = env->CallDoubleMethod(jDeviceInfo, method);
153     method = env->GetMethodID(cDeviceInfo, "getVolUpButtonTopMm", "()D");
154     device_info.volUpButtonTopMm_ = env->CallDoubleMethod(jDeviceInfo, method);
155     method = env->GetMethodID(cDeviceInfo, "getVolUpButtonBottomMm", "()D");
156     device_info.volUpButtonBottomMm_ = env->CallDoubleMethod(jDeviceInfo, method);
157     sCurrentExample =
158         createExample((strcmp(layout.begin(), kTouchButtonLayout) == 0) ? Examples::TouchButton
159                                                                         : Examples::PhysButton);
160     return sCurrentExample->setDeviceInfo(device_info, magnified, inverted);
161 }
162 
163 /*
164  * Class:     com_android_framebufferizer_NativeRenderer
165  * Method:    renderBuffer
166  * Signature: (IIIII[I)I
167  */
Java_com_android_framebufferizer_NativeRenderer_renderBuffer(JNIEnv * env,jclass,jint x,jint y,jint width,jint height,jint lineStride,jintArray jbuffer)168 extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_renderBuffer(
169     JNIEnv* env, jclass, jint x, jint y, jint width, jint height, jint lineStride,
170     jintArray jbuffer) {
171     JIntArray buffer(env, jbuffer);
172     using namespace teeui::example;
173     if (!buffer) return kFrameBufferError;
174     if (!sCurrentExample) return kLayoutExampleError;
175     return sCurrentExample->renderUIIntoBuffer((uint32_t)x, (uint32_t)y, (uint32_t)width,
176                                                (uint32_t)height, (uint32_t)lineStride,
177                                                (uint32_t*)buffer.begin(), buffer.size());
178 }
179 
180 /*
181  * Class:     com_android_confirmationui_Translation_selectLangID
182  * Method:    selectLangID
183  * Signature: (Ljava/lang/String;)V
184  */
185 extern "C" JNIEXPORT void JNICALL
Java_com_android_framebufferizer_NativeRenderer_setLanguage(JNIEnv * env,jclass,jstring jlang_id)186 Java_com_android_framebufferizer_NativeRenderer_setLanguage(JNIEnv* env, jclass, jstring jlang_id) {
187     JString lang_id(env, jlang_id);
188     if (sCurrentExample) sCurrentExample->selectLanguage(lang_id.begin());
189 }
190 /*
191  * Class:     com_android_confirmationui_Translation_selectLangID
192  * Method:    selectLangID
193  * Signature: ()[Ljava/lang/String;
194  */
195 extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_android_framebufferizer_NativeRenderer_getLanguageIdList(JNIEnv * env,jclass)196 Java_com_android_framebufferizer_NativeRenderer_getLanguageIdList(JNIEnv* env, jclass) {
197     jobjectArray language_ids;
198     teeui::localization::Languages lang_list = getLanguages();
199     const char* const* native_data = lang_list.list;
200     size_t list_size = lang_list.size;
201 
202     language_ids = (jobjectArray)env->NewObjectArray(list_size, env->FindClass("java/lang/String"),
203                                                      env->NewStringUTF(""));
204 
205     for (size_t i = 0; i < list_size; i++)
206         env->SetObjectArrayElement(language_ids, i, env->NewStringUTF(native_data[i]));
207 
208     return language_ids;
209 }
210 
211 /*
212  * Class:     com_android_framebufferizer_NativeRenderer
213  * Method:    getAvailableLayouts
214  * Signature: ()[Ljava/lang/String;
215  */
216 extern "C" JNIEXPORT jobjectArray JNICALL
Java_com_android_framebufferizer_NativeRenderer_getAvailableLayouts(JNIEnv * env,jclass)217 Java_com_android_framebufferizer_NativeRenderer_getAvailableLayouts(JNIEnv* env, jclass) {
218     using namespace teeui::example;
219     jobjectArray available_layouts;
220     const char* const* native_data = kAvailableLayouts;
221     size_t list_size = NUM_LAYOUTS;
222 
223     available_layouts = (jobjectArray)env->NewObjectArray(
224         list_size, env->FindClass("java/lang/String"), env->NewStringUTF(""));
225 
226     for (size_t i = 0; i < list_size; i++)
227         env->SetObjectArrayElement(available_layouts, i, env->NewStringUTF(native_data[i]));
228 
229     return available_layouts;
230 }
231 
232 /*
233  * Class:     com_android_framebufferizer_NativeRenderer
234  * Method:    setConfimationMessage
235  * Signature: (Ljava/lang/String;)V
236  */
237 extern "C" JNIEXPORT void JNICALL
Java_com_android_framebufferizer_NativeRenderer_setConfimationMessage(JNIEnv * env,jclass,jstring jConfirmationMessage)238 Java_com_android_framebufferizer_NativeRenderer_setConfimationMessage(
239     JNIEnv* env, jclass, jstring jConfirmationMessage) {
240     JString confirmationMessage(env, jConfirmationMessage);
241     if (sCurrentExample) sCurrentExample->setConfirmationMessage(confirmationMessage.begin());
242 }
243 
244 /*
245  * Class:     com_android_framebufferizer_NativeRenderer
246  * Method:    onEvent
247  * Signature: (III)I
248  */
Java_com_android_framebufferizer_NativeRenderer_onEvent(JNIEnv *,jclass,jint x,jint y,jint event)249 extern "C" JNIEXPORT jint JNICALL Java_com_android_framebufferizer_NativeRenderer_onEvent(
250     JNIEnv*, jclass, jint x, jint y, jint event) {
251     if (sCurrentExample) {
252         return (jint)sCurrentExample->onEvent((uint32_t)x, (uint32_t)y, (uint32_t)event);
253     }
254     return 0;
255 }