blob: 21369f9cf5f8c5903c3d5c6d54551041025a3269 [file] [log] [blame]
Dianne Hackborn69969e42010-05-04 11:40:40 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "NativeActivity"
18#include <utils/Log.h>
19
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070020#include <poll.h>
21#include <dlfcn.h>
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070022#include <fcntl.h>
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070023
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -080024#include <memory>
25
Dianne Hackborn289b9b62010-07-09 11:44:11 -070026#include <android_runtime/android_app_NativeActivity.h>
Christopher Tate6cce32b2010-07-12 18:21:36 -070027#include <android_runtime/android_util_AssetManager.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080028#include <android_runtime/android_view_Surface.h>
29#include <android_runtime/AndroidRuntime.h>
Jeff Brown9d3b1a42013-07-01 19:07:15 -070030#include <input/InputTransport.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080031
32#include <gui/Surface.h>
33
34#include <system/window.h>
35
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070036#include <utils/Looper.h>
Dianne Hackborn69969e42010-05-04 11:40:40 -070037
Steven Moreland2279b252017-07-19 09:50:45 -070038#include <nativehelper/JNIHelp.h>
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070039#include "android_os_MessageQueue.h"
40#include "android_view_InputChannel.h"
41#include "android_view_KeyEvent.h"
Dianne Hackborn69969e42010-05-04 11:40:40 -070042
dimitryf66a2232017-10-04 19:44:56 +020043#include "android-base/stringprintf.h"
Yong WU03c86602014-07-28 21:20:18 +080044#include "nativebridge/native_bridge.h"
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -080045#include "nativeloader/native_loader.h"
Yong WU03c86602014-07-28 21:20:18 +080046
Andreas Gampe987f79f2014-11-18 17:29:46 -080047#include "core_jni_helpers.h"
48
Steven Moreland2279b252017-07-19 09:50:45 -070049#include <nativehelper/ScopedUtfChars.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080050
Dianne Hackborndb28a942010-10-21 17:22:30 -070051#define LOG_TRACE(...)
Steve Block28d9f022011-10-12 17:27:03 +010052//#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070053
Dianne Hackborn69969e42010-05-04 11:40:40 -070054namespace android
55{
56
Andreas Gampeed6b9df2014-11-20 22:02:20 -080057static const bool kLogTrace = false;
58
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070059static struct {
Dianne Hackborndb28a942010-10-21 17:22:30 -070060 jmethodID finish;
Dianne Hackborn54a181b2010-06-30 18:35:14 -070061 jmethodID setWindowFlags;
62 jmethodID setWindowFormat;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070063 jmethodID showIme;
64 jmethodID hideIme;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070065} gNativeActivityClassInfo;
66
Dianne Hackborn54a181b2010-06-30 18:35:14 -070067// ------------------------------------------------------------------------
68
Dianne Hackborn289b9b62010-07-09 11:44:11 -070069struct ActivityWork {
70 int32_t cmd;
71 int32_t arg1;
72 int32_t arg2;
73};
74
75enum {
Michael Wrighta44dd262013-04-10 21:12:00 -070076 CMD_FINISH = 1,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070077 CMD_SET_WINDOW_FORMAT,
78 CMD_SET_WINDOW_FLAGS,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070079 CMD_SHOW_SOFT_INPUT,
80 CMD_HIDE_SOFT_INPUT,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070081};
82
83static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
84 ActivityWork work;
85 work.cmd = cmd;
86 work.arg1 = arg1;
87 work.arg2 = arg2;
Andreas Gampeed6b9df2014-11-20 22:02:20 -080088
89 if (kLogTrace) {
90 ALOGD("write_work: cmd=%d", cmd);
91 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070092
Dianne Hackborn289b9b62010-07-09 11:44:11 -070093restart:
94 int res = write(fd, &work, sizeof(work));
95 if (res < 0 && errno == EINTR) {
96 goto restart;
97 }
98
99 if (res == sizeof(work)) return;
100
Steve Block8564c8d2012-01-05 23:22:43 +0000101 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
102 else ALOGW("Truncated writing to work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700103}
104
105static bool read_work(int fd, ActivityWork* outWork) {
106 int res = read(fd, outWork, sizeof(ActivityWork));
107 // no need to worry about EINTR, poll loop will just come back again.
108 if (res == sizeof(ActivityWork)) return true;
109
Steve Block8564c8d2012-01-05 23:22:43 +0000110 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
111 else ALOGW("Truncated reading work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700112 return false;
113}
114
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700115/*
116 * Native state for interacting with the NativeActivity class.
117 */
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700118struct NativeCode : public ANativeActivity {
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700119 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700120 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
121 memset(&callbacks, 0, sizeof(callbacks));
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700122 dlhandle = _dlhandle;
123 createActivityFunc = _createFunc;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700124 nativeWindow = NULL;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700125 mainWorkRead = mainWorkWrite = -1;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700126 }
127
128 ~NativeCode() {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700129 if (callbacks.onDestroy != NULL) {
130 callbacks.onDestroy(this);
131 }
Adam Lesinski5c690d52017-03-17 15:17:12 -0700132 if (env != NULL) {
133 if (clazz != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700134 env->DeleteGlobalRef(clazz);
Adam Lesinski5c690d52017-03-17 15:17:12 -0700135 }
136 if (javaAssetManager != NULL) {
137 env->DeleteGlobalRef(javaAssetManager);
138 }
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700139 }
Jeff Brown603b4452012-04-06 17:39:41 -0700140 if (messageQueue != NULL && mainWorkRead >= 0) {
141 messageQueue->getLooper()->removeFd(mainWorkRead);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700142 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700143 setSurface(NULL);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700144 if (mainWorkRead >= 0) close(mainWorkRead);
145 if (mainWorkWrite >= 0) close(mainWorkWrite);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700146 if (dlhandle != NULL) {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700147 // for now don't unload... we probably should clean this
148 // up and only keep one open dlhandle per proc, since there
149 // is really no benefit to unloading the code.
150 //dlclose(dlhandle);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700151 }
152 }
153
154 void setSurface(jobject _surface) {
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700155 if (_surface != NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700156 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700157 } else {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700158 nativeWindow = NULL;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700159 }
160 }
161
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700162 ANativeActivityCallbacks callbacks;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700163
164 void* dlhandle;
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700165 ANativeActivity_createFunc* createActivityFunc;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700166
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800167 String8 internalDataPathObj;
168 String8 externalDataPathObj;
169 String8 obbPathObj;
Dianne Hackborn68267412010-07-02 18:52:01 -0700170
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700171 sp<ANativeWindow> nativeWindow;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700172 int32_t lastWindowWidth;
173 int32_t lastWindowHeight;
174
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700175 // These are used to wake up the main thread to process work.
176 int mainWorkRead;
177 int mainWorkWrite;
Jeff Brown603b4452012-04-06 17:39:41 -0700178 sp<MessageQueue> messageQueue;
Adam Lesinski5c690d52017-03-17 15:17:12 -0700179
180 // Need to hold on to a reference here in case the upper layers destroy our
181 // AssetManager.
182 jobject javaAssetManager;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700183};
184
Dianne Hackborndb28a942010-10-21 17:22:30 -0700185void android_NativeActivity_finish(ANativeActivity* activity) {
186 NativeCode* code = static_cast<NativeCode*>(activity);
187 write_work(code->mainWorkWrite, CMD_FINISH, 0);
188}
189
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700190void android_NativeActivity_setWindowFormat(
191 ANativeActivity* activity, int32_t format) {
192 NativeCode* code = static_cast<NativeCode*>(activity);
193 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
194}
195
196void android_NativeActivity_setWindowFlags(
197 ANativeActivity* activity, int32_t values, int32_t mask) {
198 NativeCode* code = static_cast<NativeCode*>(activity);
199 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
200}
201
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700202void android_NativeActivity_showSoftInput(
203 ANativeActivity* activity, int32_t flags) {
204 NativeCode* code = static_cast<NativeCode*>(activity);
205 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
206}
207
208void android_NativeActivity_hideSoftInput(
209 ANativeActivity* activity, int32_t flags) {
210 NativeCode* code = static_cast<NativeCode*>(activity);
211 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
212}
213
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700214// ------------------------------------------------------------------------
215
216/*
217 * Callback for handling native events on the application's main thread.
218 */
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700219static int mainWorkCallback(int fd, int events, void* data) {
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700220 NativeCode* code = (NativeCode*)data;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700221 if ((events & POLLIN) == 0) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700222 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700223 }
224
225 ActivityWork work;
226 if (!read_work(code->mainWorkRead, &work)) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700227 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700228 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700229
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800230 if (kLogTrace) {
231 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
232 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700233
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700234 switch (work.cmd) {
Dianne Hackborndb28a942010-10-21 17:22:30 -0700235 case CMD_FINISH: {
236 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
Jeff Brown603b4452012-04-06 17:39:41 -0700237 code->messageQueue->raiseAndClearException(code->env, "finish");
Dianne Hackborndb28a942010-10-21 17:22:30 -0700238 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700239 case CMD_SET_WINDOW_FORMAT: {
240 code->env->CallVoidMethod(code->clazz,
241 gNativeActivityClassInfo.setWindowFormat, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700242 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700243 } break;
244 case CMD_SET_WINDOW_FLAGS: {
245 code->env->CallVoidMethod(code->clazz,
246 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
Jeff Brown603b4452012-04-06 17:39:41 -0700247 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700248 } break;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700249 case CMD_SHOW_SOFT_INPUT: {
250 code->env->CallVoidMethod(code->clazz,
251 gNativeActivityClassInfo.showIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700252 code->messageQueue->raiseAndClearException(code->env, "showIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700253 } break;
254 case CMD_HIDE_SOFT_INPUT: {
255 code->env->CallVoidMethod(code->clazz,
256 gNativeActivityClassInfo.hideIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700257 code->messageQueue->raiseAndClearException(code->env, "hideIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700258 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700259 default:
Steve Block8564c8d2012-01-05 23:22:43 +0000260 ALOGW("Unknown work command: %d", work.cmd);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700261 break;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700262 }
263
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700264 return 1;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700265}
266
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700267// ------------------------------------------------------------------------
268
dimitryf66a2232017-10-04 19:44:56 +0200269static thread_local std::string g_error_msg;
270
Ashok Bhat58b8b242014-01-02 16:52:41 +0000271static jlong
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700272loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800273 jobject messageQueue, jstring internalDataDir, jstring obbDir,
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800274 jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
Dimitry Ivanovea902812016-02-23 14:25:50 -0800275 jbyteArray savedState, jobject classLoader, jstring libraryPath) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800276 if (kLogTrace) {
277 ALOGD("loadNativeCode_native");
278 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700279
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700280 ScopedUtfChars pathStr(env, path);
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800281 std::unique_ptr<NativeCode> code;
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700282 bool needs_native_bridge = false;
Yong WU03c86602014-07-28 21:20:18 +0800283
Nicolas Geoffray9cd0c702019-01-11 15:58:08 +0000284 char* nativeloader_error_msg = nullptr;
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700285 void* handle = OpenNativeLibrary(env,
286 sdkVersion,
287 pathStr.c_str(),
288 classLoader,
Nicolas Geoffrayd0ebaa92019-01-18 11:59:41 +0000289 nullptr,
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700290 libraryPath,
291 &needs_native_bridge,
Nicolas Geoffray9cd0c702019-01-11 15:58:08 +0000292 &nativeloader_error_msg);
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700293
294 if (handle == nullptr) {
Nicolas Geoffray9cd0c702019-01-11 15:58:08 +0000295 g_error_msg = nativeloader_error_msg;
296 NativeLoaderFreeErrorMessage(nativeloader_error_msg);
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700297 ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
298 pathStr.c_str(),
dimitryf66a2232017-10-04 19:44:56 +0200299 g_error_msg.c_str());
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700300 return 0;
Yong WU03c86602014-07-28 21:20:18 +0800301 }
Yong WU03c86602014-07-28 21:20:18 +0800302
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700303 void* funcPtr = NULL;
304 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
305 if (needs_native_bridge) {
306 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
307 } else {
308 funcPtr = dlsym(handle, funcStr);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700309 }
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700310
311 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
312 env->ReleaseStringUTFChars(funcName, funcStr);
313
314 if (code->createActivityFunc == NULL) {
dimitryf66a2232017-10-04 19:44:56 +0200315 g_error_msg = needs_native_bridge ? NativeBridgeGetError() : dlerror();
316 ALOGW("ANativeActivity_onCreate not found: %s", g_error_msg.c_str());
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700317 return 0;
318 }
319
320 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
321 if (code->messageQueue == NULL) {
dimitryf66a2232017-10-04 19:44:56 +0200322 g_error_msg = "Unable to retrieve native MessageQueue";
323 ALOGW("%s", g_error_msg.c_str());
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700324 return 0;
325 }
326
327 int msgpipe[2];
328 if (pipe(msgpipe)) {
dimitryf66a2232017-10-04 19:44:56 +0200329 g_error_msg = android::base::StringPrintf("could not create pipe: %s", strerror(errno));
330 ALOGW("%s", g_error_msg.c_str());
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700331 return 0;
332 }
333 code->mainWorkRead = msgpipe[0];
334 code->mainWorkWrite = msgpipe[1];
335 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
336 SLOGW_IF(result != 0, "Could not make main work read pipe "
337 "non-blocking: %s", strerror(errno));
338 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
339 SLOGW_IF(result != 0, "Could not make main work write pipe "
340 "non-blocking: %s", strerror(errno));
341 code->messageQueue->getLooper()->addFd(
342 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
343
344 code->ANativeActivity::callbacks = &code->callbacks;
345 if (env->GetJavaVM(&code->vm) < 0) {
dimitryf66a2232017-10-04 19:44:56 +0200346 g_error_msg = "NativeActivity GetJavaVM failed";
347 ALOGW("%s", g_error_msg.c_str());
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700348 return 0;
349 }
350 code->env = env;
351 code->clazz = env->NewGlobalRef(clazz);
352
353 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
354 code->internalDataPathObj = dirStr;
355 code->internalDataPath = code->internalDataPathObj.string();
356 env->ReleaseStringUTFChars(internalDataDir, dirStr);
357
358 if (externalDataDir != NULL) {
359 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
360 code->externalDataPathObj = dirStr;
361 env->ReleaseStringUTFChars(externalDataDir, dirStr);
362 }
363 code->externalDataPath = code->externalDataPathObj.string();
364
365 code->sdkVersion = sdkVersion;
366
Adam Lesinski5c690d52017-03-17 15:17:12 -0700367 code->javaAssetManager = env->NewGlobalRef(jAssetMgr);
Adam Lesinskibebfcc42018-02-12 14:27:46 -0800368 code->assetManager = NdkAssetManagerForJavaObject(env, jAssetMgr);
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700369
370 if (obbDir != NULL) {
371 dirStr = env->GetStringUTFChars(obbDir, NULL);
372 code->obbPathObj = dirStr;
373 env->ReleaseStringUTFChars(obbDir, dirStr);
374 }
375 code->obbPath = code->obbPathObj.string();
376
377 jbyte* rawSavedState = NULL;
378 jsize rawSavedSize = 0;
379 if (savedState != NULL) {
380 rawSavedState = env->GetByteArrayElements(savedState, NULL);
381 rawSavedSize = env->GetArrayLength(savedState);
382 }
383
384 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
385
386 if (rawSavedState != NULL) {
387 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
388 }
389
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800390 return (jlong)code.release();
391}
392
393static jstring getDlError_native(JNIEnv* env, jobject clazz) {
dimitryf66a2232017-10-04 19:44:56 +0200394 jstring result = env->NewStringUTF(g_error_msg.c_str());
395 g_error_msg.clear();
396 return result;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700397}
398
399static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000400unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700401{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800402 if (kLogTrace) {
403 ALOGD("unloadNativeCode_native");
404 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700405 if (handle != 0) {
406 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700407 delete code;
408 }
409}
410
411static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000412onStart_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700413{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800414 if (kLogTrace) {
415 ALOGD("onStart_native");
416 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700417 if (handle != 0) {
418 NativeCode* code = (NativeCode*)handle;
419 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700420 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700421 }
422 }
423}
424
425static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000426onResume_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700427{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800428 if (kLogTrace) {
429 ALOGD("onResume_native");
430 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700431 if (handle != 0) {
432 NativeCode* code = (NativeCode*)handle;
433 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700434 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700435 }
436 }
437}
438
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700439static jbyteArray
Ashok Bhat58b8b242014-01-02 16:52:41 +0000440onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700441{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800442 if (kLogTrace) {
443 ALOGD("onSaveInstanceState_native");
444 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700445
446 jbyteArray array = NULL;
447
Dianne Hackborn69969e42010-05-04 11:40:40 -0700448 if (handle != 0) {
449 NativeCode* code = (NativeCode*)handle;
450 if (code->callbacks.onSaveInstanceState != NULL) {
451 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700452 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
453 if (len > 0) {
454 array = env->NewByteArray(len);
455 if (array != NULL) {
456 env->SetByteArrayRegion(array, 0, len, state);
457 }
458 }
459 if (state != NULL) {
460 free(state);
461 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700462 }
463 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700464
465 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700466}
467
468static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000469onPause_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700470{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800471 if (kLogTrace) {
472 ALOGD("onPause_native");
473 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700474 if (handle != 0) {
475 NativeCode* code = (NativeCode*)handle;
476 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700477 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700478 }
479 }
480}
481
482static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000483onStop_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700484{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800485 if (kLogTrace) {
486 ALOGD("onStop_native");
487 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700488 if (handle != 0) {
489 NativeCode* code = (NativeCode*)handle;
490 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700491 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700492 }
493 }
494}
495
496static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000497onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700498{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800499 if (kLogTrace) {
500 ALOGD("onConfigurationChanged_native");
501 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700502 if (handle != 0) {
503 NativeCode* code = (NativeCode*)handle;
504 if (code->callbacks.onConfigurationChanged != NULL) {
505 code->callbacks.onConfigurationChanged(code);
506 }
507 }
508}
509
510static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000511onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700512{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800513 if (kLogTrace) {
514 ALOGD("onLowMemory_native");
515 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700516 if (handle != 0) {
517 NativeCode* code = (NativeCode*)handle;
518 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700519 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700520 }
521 }
522}
523
524static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000525onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700526{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800527 if (kLogTrace) {
528 ALOGD("onWindowFocusChanged_native");
529 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700530 if (handle != 0) {
531 NativeCode* code = (NativeCode*)handle;
532 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700533 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700534 }
535 }
536}
537
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700538static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000539onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700540{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800541 if (kLogTrace) {
542 ALOGD("onSurfaceCreated_native");
543 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700544 if (handle != 0) {
545 NativeCode* code = (NativeCode*)handle;
546 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700547 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700548 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700549 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700550 }
551 }
552}
553
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700554static int32_t getWindowProp(ANativeWindow* window, int what) {
555 int value;
556 int res = window->query(window, what, &value);
557 return res < 0 ? res : value;
558}
559
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700560static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000561onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700562 jint format, jint width, jint height)
563{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800564 if (kLogTrace) {
565 ALOGD("onSurfaceChanged_native");
566 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700567 if (handle != 0) {
568 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700569 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
570 code->setSurface(surface);
571 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700572 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700573 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700574 oldNativeWindow.get());
575 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700576 if (code->nativeWindow != NULL) {
577 if (code->callbacks.onNativeWindowCreated != NULL) {
578 code->callbacks.onNativeWindowCreated(code,
579 code->nativeWindow.get());
580 }
581 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
582 NATIVE_WINDOW_WIDTH);
583 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
584 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700585 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700586 } else {
587 // Maybe it resized?
588 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
589 NATIVE_WINDOW_WIDTH);
590 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
591 NATIVE_WINDOW_HEIGHT);
592 if (newWidth != code->lastWindowWidth
593 || newHeight != code->lastWindowHeight) {
594 if (code->callbacks.onNativeWindowResized != NULL) {
595 code->callbacks.onNativeWindowResized(code,
596 code->nativeWindow.get());
597 }
598 }
599 }
600 }
601}
602
603static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000604onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700605{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800606 if (kLogTrace) {
607 ALOGD("onSurfaceRedrawNeeded_native");
608 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700609 if (handle != 0) {
610 NativeCode* code = (NativeCode*)handle;
611 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
612 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700613 }
614 }
615}
616
617static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000618onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700619{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800620 if (kLogTrace) {
621 ALOGD("onSurfaceDestroyed_native");
622 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700623 if (handle != 0) {
624 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700625 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700626 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700627 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700628 }
629 code->setSurface(NULL);
630 }
631}
632
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700633static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000634onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700635{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800636 if (kLogTrace) {
637 ALOGD("onInputChannelCreated_native");
638 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700639 if (handle != 0) {
640 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700641 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700642 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
643 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700644 }
645 }
646}
647
648static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000649onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700650{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800651 if (kLogTrace) {
652 ALOGD("onInputChannelDestroyed_native");
653 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700654 if (handle != 0) {
655 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700656 if (code->callbacks.onInputQueueDestroyed != NULL) {
657 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
658 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700659 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700660 }
661}
662
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700663static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000664onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700665 jint x, jint y, jint w, jint h)
666{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800667 if (kLogTrace) {
668 ALOGD("onContentRectChanged_native");
669 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700670 if (handle != 0) {
671 NativeCode* code = (NativeCode*)handle;
672 if (code->callbacks.onContentRectChanged != NULL) {
673 ARect rect;
674 rect.left = x;
675 rect.top = y;
676 rect.right = x+w;
677 rect.bottom = y+h;
678 code->callbacks.onContentRectChanged(code, &rect);
679 }
680 }
681}
682
Dianne Hackborn69969e42010-05-04 11:40:40 -0700683static const JNINativeMethod g_methods[] = {
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800684 { "loadNativeCode",
Dimitry Ivanovea902812016-02-23 14:25:50 -0800685 "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[BLjava/lang/ClassLoader;Ljava/lang/String;)J",
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800686 (void*)loadNativeCode_native },
687 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000688 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
689 { "onStartNative", "(J)V", (void*)onStart_native },
690 { "onResumeNative", "(J)V", (void*)onResume_native },
691 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
692 { "onPauseNative", "(J)V", (void*)onPause_native },
693 { "onStopNative", "(J)V", (void*)onStop_native },
694 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
695 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
696 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
697 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
698 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
699 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
700 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
701 { "onInputQueueCreatedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700702 (void*)onInputQueueCreated_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000703 { "onInputQueueDestroyedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700704 (void*)onInputQueueDestroyed_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000705 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700706};
707
708static const char* const kNativeActivityPathName = "android/app/NativeActivity";
709
710int register_android_app_NativeActivity(JNIEnv* env)
711{
Steve Block5baa3a62011-12-20 16:23:08 +0000712 //ALOGD("register_android_app_NativeActivity");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800713 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700714
Andreas Gampe987f79f2014-11-18 17:29:46 -0800715 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
716 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
717 "(II)V");
718 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
719 "(I)V");
720 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
721 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700722
Andreas Gampe987f79f2014-11-18 17:29:46 -0800723 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
Dianne Hackborn69969e42010-05-04 11:40:40 -0700724}
725
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700726} // namespace android