1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #pragma once 17 18 #include <android_native_app_glue.h> 19 #include <cpu-features.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 #include <cerrno> 23 #include <unistd.h> 24 #include <dlfcn.h> 25 #include <deque> 26 #include <memory> 27 #include <string> 28 #include <vector> 29 30 #include <GLES/gl.h> 31 #include <EGL/egl.h> 32 33 #include <uv.h> 34 #include <node.h> 35 36 #include "skoala-interop.h" 37 #include "node-interop.h" 38 #include "jni-bridge.h" 39 40 struct SavedState { 41 int index; 42 }; 43 44 struct InputTextEventState { 45 int type; 46 std::string characters; 47 int cursorPosition; InputTextEventStateInputTextEventState48 InputTextEventState(int type, int cursorPosition, std::string characters) { 49 this->type = type; 50 this->cursorPosition = cursorPosition; 51 this->characters = characters; 52 } 53 }; 54 55 struct InputKeyEventState { 56 int key; 57 int modifiers; 58 int action; InputKeyEventStateInputKeyEventState59 InputKeyEventState(int key, int modifiers, int action) { 60 this->key = key; 61 this->modifiers = modifiers; 62 this->action = action; 63 } 64 }; 65 66 struct PermissionGrantedEventState { 67 int requestCode; 68 std::vector<std::string> permissions; 69 std::vector<int> grantResults; PermissionGrantedEventStatePermissionGrantedEventState70 PermissionGrantedEventState( 71 int requestCode, 72 std::vector<std::string>& permissions, 73 std::vector<int>& grantResults) { 74 this->requestCode = requestCode; 75 this->permissions = permissions; 76 this->grantResults = grantResults; 77 } 78 }; 79 80 class Engine { 81 enum Kind { 82 INIT, 83 DEINIT, 84 RESIZE, 85 REDRAW, 86 FOCUS, 87 UNFOCUS, 88 PAUSE, 89 RESUME, 90 TAP, 91 MOVE, 92 KEY 93 }; 94 struct Event { 95 Kind kind; 96 int count; 97 int args1[10]; 98 int args2[10]; 99 int arg3; 100 int target; EventEvent101 Event(Kind kind, int arg1, int arg2, int arg3) : kind(kind), count(1), arg3(arg3), target(0) { 102 args1[0] = arg1; 103 args2[0] = arg2; 104 } EventEvent105 Event(Kind kind, int arg1, int arg2) : kind(kind), count(1), arg3(0), target(0) { 106 args1[0] = arg1; 107 args2[0] = arg2; 108 } EventEvent109 Event(Kind kind, int count) : kind(kind), count(count), arg3(0), target(0) { 110 args1[0] = 0; 111 args2[0] = 0; 112 } EventEvent113 Event(Kind kind) : Event(kind, 1) {} 114 }; 115 std::deque<std::unique_ptr<Event>> _pendingEvents; 116 117 typedef void (*engine_callback_t)(Engine*, void* ctx); 118 android_app *app; 119 120 // Node runtime state. 121 std::unique_ptr<NodeRuntime> nodeRuntime; 122 std::unique_ptr<NodeScopedState> nodeScopedState; 123 124 // Graphics state. 125 EGLDisplay display; 126 EGLSurface surface; 127 EGLContext context; 128 float density; 129 130 int canDraw; 131 132 AndroidCpuFamily androidCpuFamily; 133 134 // Saved state. 135 SavedState savedState; 136 137 int initDisplay(); 138 void deinitDisplay(); 139 void resizeDisplay(); 140 141 std::shared_ptr<JNIBridge> jniBridge; checkJniBridge()142 bool checkJniBridge() { 143 if (!jniBridge) { 144 jniBridge = std::make_shared<JNIBridge>(this->app->activity->vm); 145 if (!jniBridge->init()) { 146 jniBridge.reset(); 147 return false; 148 } 149 } 150 return true; 151 } 152 153 // We may need to scale to display coordinates on some platforms. maybeScale(int * xpos,int * ypos)154 void maybeScale(int* xpos, int* ypos) { 155 float density = getContentScale(); 156 *xpos = (int)(*xpos / density); 157 *ypos = (int)(*ypos / density); 158 } 159 maybeScaleVector(Event * pointerEvent)160 void maybeScaleVector(Event* pointerEvent) { 161 float density = getContentScale(); 162 for (int i = 0; i < pointerEvent->count; i++) { 163 pointerEvent->args1[i] = (int)(pointerEvent->args1[i] / density); 164 pointerEvent->args2[i] = (int)(pointerEvent->args2[i] / density); 165 } 166 } 167 getPointersCount(const AInputEvent * event)168 int getPointersCount(const AInputEvent* event) { 169 return AMotionEvent_getPointerCount(event); 170 } 171 getCurrentAction(const AInputEvent * event)172 int getCurrentAction(const AInputEvent* event) { 173 return AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK; 174 } 175 getCurrentPointerIndex(const AInputEvent * event)176 int getCurrentPointerIndex(const AInputEvent* event) { 177 int pointerMask = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK; 178 return pointerMask >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; 179 } 180 181 jclass vibrationEffectClass; 182 183 jobject vibratorInstance; 184 185 jmethodID vibrateWithDurationMethod; 186 jmethodID vibrateWithEffectMethod; 187 jmethodID createPredefinedEffectMethod; 188 189 static RedrawerPeer* peer_factory(void* ctx, v8::Local<v8::Object> redrawer); 190 191 std::mutex locker; 192 std::deque<std::pair<engine_callback_t, void*>> cb_queue; 193 void processQueue(); 194 195 int physicalWidth; 196 int physicalHeight; 197 198 public: 199 Engine(android_app *app); 200 RedrawerPeer* peer; 201 202 int prepareNode(std::vector<std::string> &errors, const std::string& startScript); 203 204 bool initNode(); 205 void runNode(); 206 void deinitNode(); 207 208 void drawFrame(); 209 deinit()210 void deinit() { 211 deinitNode(); 212 deinitDisplay(); 213 } 214 215 int handleInput(AInputEvent* event); 216 void handleCommand(int command); 217 218 bool makeCurrent(bool attach); 219 void swapBuffers(); 220 bool checkEvents(); 221 222 float getContentScale(); 223 KNativePointer getFrame(KNativePointer peerPtr, int width, int height); 224 int32_t getFrameWidth(); 225 int32_t getFrameHeight(); 226 int32_t getPhysicalWidth(); 227 int32_t getPhysicalHeight(); 228 void requestHaptic(int32_t p1, int32_t p2); 229 int32_t getOrientation(); 230 void softKeyboard(bool show); 231 void commitInput(); 232 SkString* getClipboard(); 233 void setClipboard(const SkString&); 234 int getUnicodeChar(AInputEvent *event); 235 void globalPointer(int32_t &x, int32_t &y); 236 237 jstring androidPermissionName(const char* perm_name); 238 bool androidHasPermission(const char* perm_name); 239 bool androidExistPermission(const char* perm_name); 240 void askPermissions(std::vector<std::string> &perms); 241 242 void callOnUIThread(engine_callback_t cb, void* state); 243 }; 244