blob: fd9e714618e5ed2159851e7daefa7099375ce514 [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
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070038#include "JNIHelp.h"
39#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
Yong WU03c86602014-07-28 21:20:18 +080043#include "nativebridge/native_bridge.h"
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -080044#include "nativeloader/native_loader.h"
Yong WU03c86602014-07-28 21:20:18 +080045
Andreas Gampe987f79f2014-11-18 17:29:46 -080046#include "core_jni_helpers.h"
47
Dimitry Ivanov569834d2016-07-06 14:17:52 -070048#include "ScopedUtfChars.h"
Andreas Gampeed6b9df2014-11-20 22:02:20 -080049
Dianne Hackborndb28a942010-10-21 17:22:30 -070050#define LOG_TRACE(...)
Steve Block28d9f022011-10-12 17:27:03 +010051//#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070052
Dianne Hackborn69969e42010-05-04 11:40:40 -070053namespace android
54{
55
Andreas Gampeed6b9df2014-11-20 22:02:20 -080056static const bool kLogTrace = false;
57
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070058static struct {
Dianne Hackborndb28a942010-10-21 17:22:30 -070059 jmethodID finish;
Dianne Hackborn54a181b2010-06-30 18:35:14 -070060 jmethodID setWindowFlags;
61 jmethodID setWindowFormat;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070062 jmethodID showIme;
63 jmethodID hideIme;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070064} gNativeActivityClassInfo;
65
Dianne Hackborn54a181b2010-06-30 18:35:14 -070066// ------------------------------------------------------------------------
67
Dianne Hackborn289b9b62010-07-09 11:44:11 -070068struct ActivityWork {
69 int32_t cmd;
70 int32_t arg1;
71 int32_t arg2;
72};
73
74enum {
Michael Wrighta44dd262013-04-10 21:12:00 -070075 CMD_FINISH = 1,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070076 CMD_SET_WINDOW_FORMAT,
77 CMD_SET_WINDOW_FLAGS,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070078 CMD_SHOW_SOFT_INPUT,
79 CMD_HIDE_SOFT_INPUT,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070080};
81
82static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
83 ActivityWork work;
84 work.cmd = cmd;
85 work.arg1 = arg1;
86 work.arg2 = arg2;
Andreas Gampeed6b9df2014-11-20 22:02:20 -080087
88 if (kLogTrace) {
89 ALOGD("write_work: cmd=%d", cmd);
90 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070091
Dianne Hackborn289b9b62010-07-09 11:44:11 -070092restart:
93 int res = write(fd, &work, sizeof(work));
94 if (res < 0 && errno == EINTR) {
95 goto restart;
96 }
97
98 if (res == sizeof(work)) return;
99
Steve Block8564c8d2012-01-05 23:22:43 +0000100 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
101 else ALOGW("Truncated writing to work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700102}
103
104static bool read_work(int fd, ActivityWork* outWork) {
105 int res = read(fd, outWork, sizeof(ActivityWork));
106 // no need to worry about EINTR, poll loop will just come back again.
107 if (res == sizeof(ActivityWork)) return true;
108
Steve Block8564c8d2012-01-05 23:22:43 +0000109 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
110 else ALOGW("Truncated reading work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700111 return false;
112}
113
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700114/*
115 * Native state for interacting with the NativeActivity class.
116 */
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700117struct NativeCode : public ANativeActivity {
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700118 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700119 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
120 memset(&callbacks, 0, sizeof(callbacks));
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700121 dlhandle = _dlhandle;
122 createActivityFunc = _createFunc;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700123 nativeWindow = NULL;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700124 mainWorkRead = mainWorkWrite = -1;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700125 }
126
127 ~NativeCode() {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700128 if (callbacks.onDestroy != NULL) {
129 callbacks.onDestroy(this);
130 }
131 if (env != NULL && clazz != NULL) {
132 env->DeleteGlobalRef(clazz);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700133 }
Jeff Brown603b4452012-04-06 17:39:41 -0700134 if (messageQueue != NULL && mainWorkRead >= 0) {
135 messageQueue->getLooper()->removeFd(mainWorkRead);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700136 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700137 setSurface(NULL);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700138 if (mainWorkRead >= 0) close(mainWorkRead);
139 if (mainWorkWrite >= 0) close(mainWorkWrite);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700140 if (dlhandle != NULL) {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700141 // for now don't unload... we probably should clean this
142 // up and only keep one open dlhandle per proc, since there
143 // is really no benefit to unloading the code.
144 //dlclose(dlhandle);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700145 }
146 }
147
148 void setSurface(jobject _surface) {
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700149 if (_surface != NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700150 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700151 } else {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700152 nativeWindow = NULL;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700153 }
154 }
155
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700156 ANativeActivityCallbacks callbacks;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700157
158 void* dlhandle;
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700159 ANativeActivity_createFunc* createActivityFunc;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700160
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800161 String8 internalDataPathObj;
162 String8 externalDataPathObj;
163 String8 obbPathObj;
Dianne Hackborn68267412010-07-02 18:52:01 -0700164
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700165 sp<ANativeWindow> nativeWindow;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700166 int32_t lastWindowWidth;
167 int32_t lastWindowHeight;
168
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700169 // These are used to wake up the main thread to process work.
170 int mainWorkRead;
171 int mainWorkWrite;
Jeff Brown603b4452012-04-06 17:39:41 -0700172 sp<MessageQueue> messageQueue;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700173};
174
Dianne Hackborndb28a942010-10-21 17:22:30 -0700175void android_NativeActivity_finish(ANativeActivity* activity) {
176 NativeCode* code = static_cast<NativeCode*>(activity);
177 write_work(code->mainWorkWrite, CMD_FINISH, 0);
178}
179
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700180void android_NativeActivity_setWindowFormat(
181 ANativeActivity* activity, int32_t format) {
182 NativeCode* code = static_cast<NativeCode*>(activity);
183 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
184}
185
186void android_NativeActivity_setWindowFlags(
187 ANativeActivity* activity, int32_t values, int32_t mask) {
188 NativeCode* code = static_cast<NativeCode*>(activity);
189 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
190}
191
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700192void android_NativeActivity_showSoftInput(
193 ANativeActivity* activity, int32_t flags) {
194 NativeCode* code = static_cast<NativeCode*>(activity);
195 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
196}
197
198void android_NativeActivity_hideSoftInput(
199 ANativeActivity* activity, int32_t flags) {
200 NativeCode* code = static_cast<NativeCode*>(activity);
201 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
202}
203
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700204// ------------------------------------------------------------------------
205
206/*
207 * Callback for handling native events on the application's main thread.
208 */
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700209static int mainWorkCallback(int fd, int events, void* data) {
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700210 NativeCode* code = (NativeCode*)data;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700211 if ((events & POLLIN) == 0) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700212 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700213 }
214
215 ActivityWork work;
216 if (!read_work(code->mainWorkRead, &work)) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700217 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700218 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700219
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800220 if (kLogTrace) {
221 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
222 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700223
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700224 switch (work.cmd) {
Dianne Hackborndb28a942010-10-21 17:22:30 -0700225 case CMD_FINISH: {
226 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
Jeff Brown603b4452012-04-06 17:39:41 -0700227 code->messageQueue->raiseAndClearException(code->env, "finish");
Dianne Hackborndb28a942010-10-21 17:22:30 -0700228 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700229 case CMD_SET_WINDOW_FORMAT: {
230 code->env->CallVoidMethod(code->clazz,
231 gNativeActivityClassInfo.setWindowFormat, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700232 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700233 } break;
234 case CMD_SET_WINDOW_FLAGS: {
235 code->env->CallVoidMethod(code->clazz,
236 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
Jeff Brown603b4452012-04-06 17:39:41 -0700237 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700238 } break;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700239 case CMD_SHOW_SOFT_INPUT: {
240 code->env->CallVoidMethod(code->clazz,
241 gNativeActivityClassInfo.showIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700242 code->messageQueue->raiseAndClearException(code->env, "showIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700243 } break;
244 case CMD_HIDE_SOFT_INPUT: {
245 code->env->CallVoidMethod(code->clazz,
246 gNativeActivityClassInfo.hideIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700247 code->messageQueue->raiseAndClearException(code->env, "hideIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700248 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700249 default:
Steve Block8564c8d2012-01-05 23:22:43 +0000250 ALOGW("Unknown work command: %d", work.cmd);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700251 break;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700252 }
253
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700254 return 1;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700255}
256
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700257// ------------------------------------------------------------------------
258
Ashok Bhat58b8b242014-01-02 16:52:41 +0000259static jlong
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700260loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800261 jobject messageQueue, jstring internalDataDir, jstring obbDir,
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800262 jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
Dimitry Ivanovea902812016-02-23 14:25:50 -0800263 jbyteArray savedState, jobject classLoader, jstring libraryPath) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800264 if (kLogTrace) {
265 ALOGD("loadNativeCode_native");
266 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700267
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700268 ScopedUtfChars pathStr(env, path);
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800269 std::unique_ptr<NativeCode> code;
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700270 bool needs_native_bridge = false;
271 std::string error_msg;
Yong WU03c86602014-07-28 21:20:18 +0800272
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700273 void* handle = OpenNativeLibrary(env,
274 sdkVersion,
275 pathStr.c_str(),
276 classLoader,
277 libraryPath,
278 &needs_native_bridge,
279 &error_msg);
280
281 if (handle == nullptr) {
282 ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
283 pathStr.c_str(),
284 error_msg.c_str());
285 return 0;
Yong WU03c86602014-07-28 21:20:18 +0800286 }
Yong WU03c86602014-07-28 21:20:18 +0800287
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700288 void* funcPtr = NULL;
289 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
290 if (needs_native_bridge) {
291 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
292 } else {
293 funcPtr = dlsym(handle, funcStr);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700294 }
Dimitry Ivanov569834d2016-07-06 14:17:52 -0700295
296 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
297 env->ReleaseStringUTFChars(funcName, funcStr);
298
299 if (code->createActivityFunc == NULL) {
300 ALOGW("ANativeActivity_onCreate not found");
301 return 0;
302 }
303
304 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
305 if (code->messageQueue == NULL) {
306 ALOGW("Unable to retrieve native MessageQueue");
307 return 0;
308 }
309
310 int msgpipe[2];
311 if (pipe(msgpipe)) {
312 ALOGW("could not create pipe: %s", strerror(errno));
313 return 0;
314 }
315 code->mainWorkRead = msgpipe[0];
316 code->mainWorkWrite = msgpipe[1];
317 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
318 SLOGW_IF(result != 0, "Could not make main work read pipe "
319 "non-blocking: %s", strerror(errno));
320 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
321 SLOGW_IF(result != 0, "Could not make main work write pipe "
322 "non-blocking: %s", strerror(errno));
323 code->messageQueue->getLooper()->addFd(
324 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
325
326 code->ANativeActivity::callbacks = &code->callbacks;
327 if (env->GetJavaVM(&code->vm) < 0) {
328 ALOGW("NativeActivity GetJavaVM failed");
329 return 0;
330 }
331 code->env = env;
332 code->clazz = env->NewGlobalRef(clazz);
333
334 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
335 code->internalDataPathObj = dirStr;
336 code->internalDataPath = code->internalDataPathObj.string();
337 env->ReleaseStringUTFChars(internalDataDir, dirStr);
338
339 if (externalDataDir != NULL) {
340 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
341 code->externalDataPathObj = dirStr;
342 env->ReleaseStringUTFChars(externalDataDir, dirStr);
343 }
344 code->externalDataPath = code->externalDataPathObj.string();
345
346 code->sdkVersion = sdkVersion;
347
348 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
349
350 if (obbDir != NULL) {
351 dirStr = env->GetStringUTFChars(obbDir, NULL);
352 code->obbPathObj = dirStr;
353 env->ReleaseStringUTFChars(obbDir, dirStr);
354 }
355 code->obbPath = code->obbPathObj.string();
356
357 jbyte* rawSavedState = NULL;
358 jsize rawSavedSize = 0;
359 if (savedState != NULL) {
360 rawSavedState = env->GetByteArrayElements(savedState, NULL);
361 rawSavedSize = env->GetArrayLength(savedState);
362 }
363
364 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
365
366 if (rawSavedState != NULL) {
367 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
368 }
369
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800370 return (jlong)code.release();
371}
372
373static jstring getDlError_native(JNIEnv* env, jobject clazz) {
374 return env->NewStringUTF(dlerror());
Dianne Hackborn69969e42010-05-04 11:40:40 -0700375}
376
377static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000378unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700379{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800380 if (kLogTrace) {
381 ALOGD("unloadNativeCode_native");
382 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700383 if (handle != 0) {
384 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700385 delete code;
386 }
387}
388
389static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000390onStart_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700391{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800392 if (kLogTrace) {
393 ALOGD("onStart_native");
394 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700395 if (handle != 0) {
396 NativeCode* code = (NativeCode*)handle;
397 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700398 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700399 }
400 }
401}
402
403static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000404onResume_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700405{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800406 if (kLogTrace) {
407 ALOGD("onResume_native");
408 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700409 if (handle != 0) {
410 NativeCode* code = (NativeCode*)handle;
411 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700412 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700413 }
414 }
415}
416
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700417static jbyteArray
Ashok Bhat58b8b242014-01-02 16:52:41 +0000418onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700419{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800420 if (kLogTrace) {
421 ALOGD("onSaveInstanceState_native");
422 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700423
424 jbyteArray array = NULL;
425
Dianne Hackborn69969e42010-05-04 11:40:40 -0700426 if (handle != 0) {
427 NativeCode* code = (NativeCode*)handle;
428 if (code->callbacks.onSaveInstanceState != NULL) {
429 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700430 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
431 if (len > 0) {
432 array = env->NewByteArray(len);
433 if (array != NULL) {
434 env->SetByteArrayRegion(array, 0, len, state);
435 }
436 }
437 if (state != NULL) {
438 free(state);
439 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700440 }
441 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700442
443 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700444}
445
446static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000447onPause_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700448{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800449 if (kLogTrace) {
450 ALOGD("onPause_native");
451 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700452 if (handle != 0) {
453 NativeCode* code = (NativeCode*)handle;
454 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700455 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700456 }
457 }
458}
459
460static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000461onStop_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700462{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800463 if (kLogTrace) {
464 ALOGD("onStop_native");
465 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700466 if (handle != 0) {
467 NativeCode* code = (NativeCode*)handle;
468 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700469 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700470 }
471 }
472}
473
474static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000475onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700476{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800477 if (kLogTrace) {
478 ALOGD("onConfigurationChanged_native");
479 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700480 if (handle != 0) {
481 NativeCode* code = (NativeCode*)handle;
482 if (code->callbacks.onConfigurationChanged != NULL) {
483 code->callbacks.onConfigurationChanged(code);
484 }
485 }
486}
487
488static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000489onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700490{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800491 if (kLogTrace) {
492 ALOGD("onLowMemory_native");
493 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700494 if (handle != 0) {
495 NativeCode* code = (NativeCode*)handle;
496 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700497 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700498 }
499 }
500}
501
502static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000503onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700504{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800505 if (kLogTrace) {
506 ALOGD("onWindowFocusChanged_native");
507 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700508 if (handle != 0) {
509 NativeCode* code = (NativeCode*)handle;
510 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700511 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700512 }
513 }
514}
515
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700516static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000517onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700518{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800519 if (kLogTrace) {
520 ALOGD("onSurfaceCreated_native");
521 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700522 if (handle != 0) {
523 NativeCode* code = (NativeCode*)handle;
524 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700525 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700526 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700527 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700528 }
529 }
530}
531
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700532static int32_t getWindowProp(ANativeWindow* window, int what) {
533 int value;
534 int res = window->query(window, what, &value);
535 return res < 0 ? res : value;
536}
537
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700538static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000539onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700540 jint format, jint width, jint height)
541{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800542 if (kLogTrace) {
543 ALOGD("onSurfaceChanged_native");
544 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700545 if (handle != 0) {
546 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700547 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
548 code->setSurface(surface);
549 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700550 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700551 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700552 oldNativeWindow.get());
553 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700554 if (code->nativeWindow != NULL) {
555 if (code->callbacks.onNativeWindowCreated != NULL) {
556 code->callbacks.onNativeWindowCreated(code,
557 code->nativeWindow.get());
558 }
559 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
560 NATIVE_WINDOW_WIDTH);
561 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
562 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700563 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700564 } else {
565 // Maybe it resized?
566 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
567 NATIVE_WINDOW_WIDTH);
568 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
569 NATIVE_WINDOW_HEIGHT);
570 if (newWidth != code->lastWindowWidth
571 || newHeight != code->lastWindowHeight) {
572 if (code->callbacks.onNativeWindowResized != NULL) {
573 code->callbacks.onNativeWindowResized(code,
574 code->nativeWindow.get());
575 }
576 }
577 }
578 }
579}
580
581static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000582onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700583{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800584 if (kLogTrace) {
585 ALOGD("onSurfaceRedrawNeeded_native");
586 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700587 if (handle != 0) {
588 NativeCode* code = (NativeCode*)handle;
589 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
590 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700591 }
592 }
593}
594
595static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000596onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700597{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800598 if (kLogTrace) {
599 ALOGD("onSurfaceDestroyed_native");
600 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700601 if (handle != 0) {
602 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700603 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700604 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700605 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700606 }
607 code->setSurface(NULL);
608 }
609}
610
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700611static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000612onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700613{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800614 if (kLogTrace) {
615 ALOGD("onInputChannelCreated_native");
616 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700617 if (handle != 0) {
618 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700619 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700620 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
621 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700622 }
623 }
624}
625
626static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000627onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700628{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800629 if (kLogTrace) {
630 ALOGD("onInputChannelDestroyed_native");
631 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700632 if (handle != 0) {
633 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700634 if (code->callbacks.onInputQueueDestroyed != NULL) {
635 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
636 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700637 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700638 }
639}
640
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700641static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000642onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700643 jint x, jint y, jint w, jint h)
644{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800645 if (kLogTrace) {
646 ALOGD("onContentRectChanged_native");
647 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700648 if (handle != 0) {
649 NativeCode* code = (NativeCode*)handle;
650 if (code->callbacks.onContentRectChanged != NULL) {
651 ARect rect;
652 rect.left = x;
653 rect.top = y;
654 rect.right = x+w;
655 rect.bottom = y+h;
656 code->callbacks.onContentRectChanged(code, &rect);
657 }
658 }
659}
660
Dianne Hackborn69969e42010-05-04 11:40:40 -0700661static const JNINativeMethod g_methods[] = {
Dmitriy Ivanov6f06ad72015-11-15 14:58:36 -0800662 { "loadNativeCode",
Dimitry Ivanovea902812016-02-23 14:25:50 -0800663 "(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 -0800664 (void*)loadNativeCode_native },
665 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000666 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
667 { "onStartNative", "(J)V", (void*)onStart_native },
668 { "onResumeNative", "(J)V", (void*)onResume_native },
669 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
670 { "onPauseNative", "(J)V", (void*)onPause_native },
671 { "onStopNative", "(J)V", (void*)onStop_native },
672 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
673 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
674 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
675 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
676 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
677 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
678 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
679 { "onInputQueueCreatedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700680 (void*)onInputQueueCreated_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000681 { "onInputQueueDestroyedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700682 (void*)onInputQueueDestroyed_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000683 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700684};
685
686static const char* const kNativeActivityPathName = "android/app/NativeActivity";
687
688int register_android_app_NativeActivity(JNIEnv* env)
689{
Steve Block5baa3a62011-12-20 16:23:08 +0000690 //ALOGD("register_android_app_NativeActivity");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800691 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700692
Andreas Gampe987f79f2014-11-18 17:29:46 -0800693 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
694 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
695 "(II)V");
696 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
697 "(I)V");
698 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
699 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700700
Andreas Gampe987f79f2014-11-18 17:29:46 -0800701 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
Dianne Hackborn69969e42010-05-04 11:40:40 -0700702}
703
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700704} // namespace android