blob: 88a56d2084d0f3f4e1b5db39a5087dc1f4ff0e62 [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 Ivanov048a0db2015-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 Ivanov048a0db2015-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
Andreas Gampeed6b9df2014-11-20 22:02:20 -080048
Dianne Hackborndb28a942010-10-21 17:22:30 -070049#define LOG_TRACE(...)
Steve Block28d9f022011-10-12 17:27:03 +010050//#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070051
Dianne Hackborn69969e42010-05-04 11:40:40 -070052namespace android
53{
54
Andreas Gampeed6b9df2014-11-20 22:02:20 -080055static const bool kLogTrace = false;
56
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070057static struct {
Dianne Hackborndb28a942010-10-21 17:22:30 -070058 jmethodID finish;
Dianne Hackborn54a181b2010-06-30 18:35:14 -070059 jmethodID setWindowFlags;
60 jmethodID setWindowFormat;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070061 jmethodID showIme;
62 jmethodID hideIme;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070063} gNativeActivityClassInfo;
64
Dianne Hackborn54a181b2010-06-30 18:35:14 -070065// ------------------------------------------------------------------------
66
Dianne Hackborn289b9b62010-07-09 11:44:11 -070067struct ActivityWork {
68 int32_t cmd;
69 int32_t arg1;
70 int32_t arg2;
71};
72
73enum {
Michael Wrighta44dd262013-04-10 21:12:00 -070074 CMD_FINISH = 1,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070075 CMD_SET_WINDOW_FORMAT,
76 CMD_SET_WINDOW_FLAGS,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070077 CMD_SHOW_SOFT_INPUT,
78 CMD_HIDE_SOFT_INPUT,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070079};
80
81static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
82 ActivityWork work;
83 work.cmd = cmd;
84 work.arg1 = arg1;
85 work.arg2 = arg2;
Andreas Gampeed6b9df2014-11-20 22:02:20 -080086
87 if (kLogTrace) {
88 ALOGD("write_work: cmd=%d", cmd);
89 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070090
Dianne Hackborn289b9b62010-07-09 11:44:11 -070091restart:
92 int res = write(fd, &work, sizeof(work));
93 if (res < 0 && errno == EINTR) {
94 goto restart;
95 }
96
97 if (res == sizeof(work)) return;
98
Steve Block8564c8d2012-01-05 23:22:43 +000099 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
100 else ALOGW("Truncated writing to work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700101}
102
103static bool read_work(int fd, ActivityWork* outWork) {
104 int res = read(fd, outWork, sizeof(ActivityWork));
105 // no need to worry about EINTR, poll loop will just come back again.
106 if (res == sizeof(ActivityWork)) return true;
107
Steve Block8564c8d2012-01-05 23:22:43 +0000108 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
109 else ALOGW("Truncated reading work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700110 return false;
111}
112
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700113/*
114 * Native state for interacting with the NativeActivity class.
115 */
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700116struct NativeCode : public ANativeActivity {
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700117 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700118 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
119 memset(&callbacks, 0, sizeof(callbacks));
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700120 dlhandle = _dlhandle;
121 createActivityFunc = _createFunc;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700122 nativeWindow = NULL;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700123 mainWorkRead = mainWorkWrite = -1;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700124 }
125
126 ~NativeCode() {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700127 if (callbacks.onDestroy != NULL) {
128 callbacks.onDestroy(this);
129 }
130 if (env != NULL && clazz != NULL) {
131 env->DeleteGlobalRef(clazz);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700132 }
Jeff Brown603b4452012-04-06 17:39:41 -0700133 if (messageQueue != NULL && mainWorkRead >= 0) {
134 messageQueue->getLooper()->removeFd(mainWorkRead);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700135 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700136 setSurface(NULL);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700137 if (mainWorkRead >= 0) close(mainWorkRead);
138 if (mainWorkWrite >= 0) close(mainWorkWrite);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700139 if (dlhandle != NULL) {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700140 // for now don't unload... we probably should clean this
141 // up and only keep one open dlhandle per proc, since there
142 // is really no benefit to unloading the code.
143 //dlclose(dlhandle);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700144 }
145 }
146
147 void setSurface(jobject _surface) {
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700148 if (_surface != NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700149 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700150 } else {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700151 nativeWindow = NULL;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700152 }
153 }
154
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700155 ANativeActivityCallbacks callbacks;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700156
157 void* dlhandle;
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700158 ANativeActivity_createFunc* createActivityFunc;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700159
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800160 String8 internalDataPathObj;
161 String8 externalDataPathObj;
162 String8 obbPathObj;
Dianne Hackborn68267412010-07-02 18:52:01 -0700163
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700164 sp<ANativeWindow> nativeWindow;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700165 int32_t lastWindowWidth;
166 int32_t lastWindowHeight;
167
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700168 // These are used to wake up the main thread to process work.
169 int mainWorkRead;
170 int mainWorkWrite;
Jeff Brown603b4452012-04-06 17:39:41 -0700171 sp<MessageQueue> messageQueue;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700172};
173
Dianne Hackborndb28a942010-10-21 17:22:30 -0700174void android_NativeActivity_finish(ANativeActivity* activity) {
175 NativeCode* code = static_cast<NativeCode*>(activity);
176 write_work(code->mainWorkWrite, CMD_FINISH, 0);
177}
178
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700179void android_NativeActivity_setWindowFormat(
180 ANativeActivity* activity, int32_t format) {
181 NativeCode* code = static_cast<NativeCode*>(activity);
182 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
183}
184
185void android_NativeActivity_setWindowFlags(
186 ANativeActivity* activity, int32_t values, int32_t mask) {
187 NativeCode* code = static_cast<NativeCode*>(activity);
188 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
189}
190
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700191void android_NativeActivity_showSoftInput(
192 ANativeActivity* activity, int32_t flags) {
193 NativeCode* code = static_cast<NativeCode*>(activity);
194 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
195}
196
197void android_NativeActivity_hideSoftInput(
198 ANativeActivity* activity, int32_t flags) {
199 NativeCode* code = static_cast<NativeCode*>(activity);
200 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
201}
202
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700203// ------------------------------------------------------------------------
204
205/*
206 * Callback for handling native events on the application's main thread.
207 */
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700208static int mainWorkCallback(int fd, int events, void* data) {
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700209 NativeCode* code = (NativeCode*)data;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700210 if ((events & POLLIN) == 0) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700211 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700212 }
213
214 ActivityWork work;
215 if (!read_work(code->mainWorkRead, &work)) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700216 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700217 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700218
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800219 if (kLogTrace) {
220 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
221 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700222
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700223 switch (work.cmd) {
Dianne Hackborndb28a942010-10-21 17:22:30 -0700224 case CMD_FINISH: {
225 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
Jeff Brown603b4452012-04-06 17:39:41 -0700226 code->messageQueue->raiseAndClearException(code->env, "finish");
Dianne Hackborndb28a942010-10-21 17:22:30 -0700227 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700228 case CMD_SET_WINDOW_FORMAT: {
229 code->env->CallVoidMethod(code->clazz,
230 gNativeActivityClassInfo.setWindowFormat, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700231 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700232 } break;
233 case CMD_SET_WINDOW_FLAGS: {
234 code->env->CallVoidMethod(code->clazz,
235 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
Jeff Brown603b4452012-04-06 17:39:41 -0700236 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700237 } break;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700238 case CMD_SHOW_SOFT_INPUT: {
239 code->env->CallVoidMethod(code->clazz,
240 gNativeActivityClassInfo.showIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700241 code->messageQueue->raiseAndClearException(code->env, "showIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700242 } break;
243 case CMD_HIDE_SOFT_INPUT: {
244 code->env->CallVoidMethod(code->clazz,
245 gNativeActivityClassInfo.hideIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700246 code->messageQueue->raiseAndClearException(code->env, "hideIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700247 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700248 default:
Steve Block8564c8d2012-01-05 23:22:43 +0000249 ALOGW("Unknown work command: %d", work.cmd);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700250 break;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700251 }
252
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700253 return 1;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700254}
255
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700256// ------------------------------------------------------------------------
257
Ashok Bhat58b8b242014-01-02 16:52:41 +0000258static jlong
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700259loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800260 jobject messageQueue, jstring internalDataDir, jstring obbDir,
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800261 jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
262 jbyteArray savedState, jobject classLoader, jstring libraryPath,
263 jstring isolationPath) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800264 if (kLogTrace) {
265 ALOGD("loadNativeCode_native");
266 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700267
Dianne Hackborn69969e42010-05-04 11:40:40 -0700268 const char* pathStr = env->GetStringUTFChars(path, NULL);
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800269 std::unique_ptr<NativeCode> code;
Yong WU03c86602014-07-28 21:20:18 +0800270 bool needNativeBridge = false;
271
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800272 void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader,
Dimitry Ivanov75b10ec2015-12-11 17:34:21 -0800273 false, libraryPath, isolationPath);
Yong WU03c86602014-07-28 21:20:18 +0800274 if (handle == NULL) {
275 if (NativeBridgeIsSupported(pathStr)) {
276 handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
277 needNativeBridge = true;
278 }
279 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700280 env->ReleaseStringUTFChars(path, pathStr);
Yong WU03c86602014-07-28 21:20:18 +0800281
Dianne Hackborn69969e42010-05-04 11:40:40 -0700282 if (handle != NULL) {
Yong WU03c86602014-07-28 21:20:18 +0800283 void* funcPtr = NULL;
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700284 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
Yong WU03c86602014-07-28 21:20:18 +0800285 if (needNativeBridge) {
286 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
287 } else {
288 funcPtr = dlsym(handle, funcStr);
289 }
290
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800291 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700292 env->ReleaseStringUTFChars(funcName, funcStr);
Yong WU03c86602014-07-28 21:20:18 +0800293
Dianne Hackborn69969e42010-05-04 11:40:40 -0700294 if (code->createActivityFunc == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000295 ALOGW("ANativeActivity_onCreate not found");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700296 return 0;
297 }
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700298
Jeff Brown603b4452012-04-06 17:39:41 -0700299 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
300 if (code->messageQueue == NULL) {
301 ALOGW("Unable to retrieve native MessageQueue");
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700302 return 0;
303 }
304
305 int msgpipe[2];
306 if (pipe(msgpipe)) {
Steve Block8564c8d2012-01-05 23:22:43 +0000307 ALOGW("could not create pipe: %s", strerror(errno));
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700308 return 0;
309 }
310 code->mainWorkRead = msgpipe[0];
311 code->mainWorkWrite = msgpipe[1];
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700312 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
313 SLOGW_IF(result != 0, "Could not make main work read pipe "
314 "non-blocking: %s", strerror(errno));
315 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
316 SLOGW_IF(result != 0, "Could not make main work write pipe "
317 "non-blocking: %s", strerror(errno));
Jeff Brown603b4452012-04-06 17:39:41 -0700318 code->messageQueue->getLooper()->addFd(
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800319 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700320
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700321 code->ANativeActivity::callbacks = &code->callbacks;
322 if (env->GetJavaVM(&code->vm) < 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000323 ALOGW("NativeActivity GetJavaVM failed");
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700324 return 0;
325 }
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700326 code->env = env;
327 code->clazz = env->NewGlobalRef(clazz);
Christopher Tate6cce32b2010-07-12 18:21:36 -0700328
Dianne Hackborn68267412010-07-02 18:52:01 -0700329 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800330 code->internalDataPathObj = dirStr;
331 code->internalDataPath = code->internalDataPathObj.string();
332 env->ReleaseStringUTFChars(internalDataDir, dirStr);
Dianne Hackborn68267412010-07-02 18:52:01 -0700333
Jeff Sharkeye0475c82013-08-15 11:50:02 -0700334 if (externalDataDir != NULL) {
335 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
336 code->externalDataPathObj = dirStr;
337 env->ReleaseStringUTFChars(externalDataDir, dirStr);
338 }
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800339 code->externalDataPath = code->externalDataPathObj.string();
Christopher Tate6cce32b2010-07-12 18:21:36 -0700340
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700341 code->sdkVersion = sdkVersion;
Dianne Hackborn68267412010-07-02 18:52:01 -0700342
Christopher Tate6cce32b2010-07-12 18:21:36 -0700343 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
344
Jeff Sharkeye0475c82013-08-15 11:50:02 -0700345 if (obbDir != NULL) {
346 dirStr = env->GetStringUTFChars(obbDir, NULL);
347 code->obbPathObj = dirStr;
348 env->ReleaseStringUTFChars(obbDir, dirStr);
349 }
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800350 code->obbPath = code->obbPathObj.string();
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800351
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700352 jbyte* rawSavedState = NULL;
353 jsize rawSavedSize = 0;
354 if (savedState != NULL) {
355 rawSavedState = env->GetByteArrayElements(savedState, NULL);
356 rawSavedSize = env->GetArrayLength(savedState);
357 }
358
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800359 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700360
361 if (rawSavedState != NULL) {
362 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
363 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700364 }
365
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800366 return (jlong)code.release();
367}
368
369static jstring getDlError_native(JNIEnv* env, jobject clazz) {
370 return env->NewStringUTF(dlerror());
Dianne Hackborn69969e42010-05-04 11:40:40 -0700371}
372
373static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000374unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700375{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800376 if (kLogTrace) {
377 ALOGD("unloadNativeCode_native");
378 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700379 if (handle != 0) {
380 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700381 delete code;
382 }
383}
384
385static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000386onStart_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700387{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800388 if (kLogTrace) {
389 ALOGD("onStart_native");
390 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700391 if (handle != 0) {
392 NativeCode* code = (NativeCode*)handle;
393 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700394 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700395 }
396 }
397}
398
399static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000400onResume_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("onResume_native");
404 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700405 if (handle != 0) {
406 NativeCode* code = (NativeCode*)handle;
407 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700408 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700409 }
410 }
411}
412
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700413static jbyteArray
Ashok Bhat58b8b242014-01-02 16:52:41 +0000414onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700415{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800416 if (kLogTrace) {
417 ALOGD("onSaveInstanceState_native");
418 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700419
420 jbyteArray array = NULL;
421
Dianne Hackborn69969e42010-05-04 11:40:40 -0700422 if (handle != 0) {
423 NativeCode* code = (NativeCode*)handle;
424 if (code->callbacks.onSaveInstanceState != NULL) {
425 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700426 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
427 if (len > 0) {
428 array = env->NewByteArray(len);
429 if (array != NULL) {
430 env->SetByteArrayRegion(array, 0, len, state);
431 }
432 }
433 if (state != NULL) {
434 free(state);
435 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700436 }
437 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700438
439 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700440}
441
442static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000443onPause_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700444{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800445 if (kLogTrace) {
446 ALOGD("onPause_native");
447 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700448 if (handle != 0) {
449 NativeCode* code = (NativeCode*)handle;
450 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700451 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700452 }
453 }
454}
455
456static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000457onStop_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700458{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800459 if (kLogTrace) {
460 ALOGD("onStop_native");
461 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700462 if (handle != 0) {
463 NativeCode* code = (NativeCode*)handle;
464 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700465 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700466 }
467 }
468}
469
470static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000471onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700472{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800473 if (kLogTrace) {
474 ALOGD("onConfigurationChanged_native");
475 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700476 if (handle != 0) {
477 NativeCode* code = (NativeCode*)handle;
478 if (code->callbacks.onConfigurationChanged != NULL) {
479 code->callbacks.onConfigurationChanged(code);
480 }
481 }
482}
483
484static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000485onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700486{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800487 if (kLogTrace) {
488 ALOGD("onLowMemory_native");
489 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700490 if (handle != 0) {
491 NativeCode* code = (NativeCode*)handle;
492 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700493 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700494 }
495 }
496}
497
498static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000499onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700500{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800501 if (kLogTrace) {
502 ALOGD("onWindowFocusChanged_native");
503 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700504 if (handle != 0) {
505 NativeCode* code = (NativeCode*)handle;
506 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700507 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700508 }
509 }
510}
511
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700512static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000513onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700514{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800515 if (kLogTrace) {
516 ALOGD("onSurfaceCreated_native");
517 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700518 if (handle != 0) {
519 NativeCode* code = (NativeCode*)handle;
520 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700521 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700522 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700523 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700524 }
525 }
526}
527
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700528static int32_t getWindowProp(ANativeWindow* window, int what) {
529 int value;
530 int res = window->query(window, what, &value);
531 return res < 0 ? res : value;
532}
533
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700534static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000535onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700536 jint format, jint width, jint height)
537{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800538 if (kLogTrace) {
539 ALOGD("onSurfaceChanged_native");
540 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700541 if (handle != 0) {
542 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700543 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
544 code->setSurface(surface);
545 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700546 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700547 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700548 oldNativeWindow.get());
549 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700550 if (code->nativeWindow != NULL) {
551 if (code->callbacks.onNativeWindowCreated != NULL) {
552 code->callbacks.onNativeWindowCreated(code,
553 code->nativeWindow.get());
554 }
555 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
556 NATIVE_WINDOW_WIDTH);
557 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
558 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700559 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700560 } else {
561 // Maybe it resized?
562 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
563 NATIVE_WINDOW_WIDTH);
564 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
565 NATIVE_WINDOW_HEIGHT);
566 if (newWidth != code->lastWindowWidth
567 || newHeight != code->lastWindowHeight) {
568 if (code->callbacks.onNativeWindowResized != NULL) {
569 code->callbacks.onNativeWindowResized(code,
570 code->nativeWindow.get());
571 }
572 }
573 }
574 }
575}
576
577static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000578onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700579{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800580 if (kLogTrace) {
581 ALOGD("onSurfaceRedrawNeeded_native");
582 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700583 if (handle != 0) {
584 NativeCode* code = (NativeCode*)handle;
585 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
586 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700587 }
588 }
589}
590
591static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000592onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700593{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800594 if (kLogTrace) {
595 ALOGD("onSurfaceDestroyed_native");
596 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700597 if (handle != 0) {
598 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700599 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700600 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700601 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700602 }
603 code->setSurface(NULL);
604 }
605}
606
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700607static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000608onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700609{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800610 if (kLogTrace) {
611 ALOGD("onInputChannelCreated_native");
612 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700613 if (handle != 0) {
614 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700615 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700616 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
617 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700618 }
619 }
620}
621
622static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000623onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700624{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800625 if (kLogTrace) {
626 ALOGD("onInputChannelDestroyed_native");
627 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700628 if (handle != 0) {
629 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700630 if (code->callbacks.onInputQueueDestroyed != NULL) {
631 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
632 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700633 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700634 }
635}
636
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700637static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000638onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700639 jint x, jint y, jint w, jint h)
640{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800641 if (kLogTrace) {
642 ALOGD("onContentRectChanged_native");
643 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700644 if (handle != 0) {
645 NativeCode* code = (NativeCode*)handle;
646 if (code->callbacks.onContentRectChanged != NULL) {
647 ARect rect;
648 rect.left = x;
649 rect.top = y;
650 rect.right = x+w;
651 rect.bottom = y+h;
652 code->callbacks.onContentRectChanged(code, &rect);
653 }
654 }
655}
656
Dianne Hackborn69969e42010-05-04 11:40:40 -0700657static const JNINativeMethod g_methods[] = {
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800658 { "loadNativeCode",
659 "(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;Ljava/lang/String;)J",
660 (void*)loadNativeCode_native },
661 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000662 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
663 { "onStartNative", "(J)V", (void*)onStart_native },
664 { "onResumeNative", "(J)V", (void*)onResume_native },
665 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
666 { "onPauseNative", "(J)V", (void*)onPause_native },
667 { "onStopNative", "(J)V", (void*)onStop_native },
668 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
669 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
670 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
671 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
672 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
673 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
674 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
675 { "onInputQueueCreatedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700676 (void*)onInputQueueCreated_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000677 { "onInputQueueDestroyedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700678 (void*)onInputQueueDestroyed_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000679 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700680};
681
682static const char* const kNativeActivityPathName = "android/app/NativeActivity";
683
684int register_android_app_NativeActivity(JNIEnv* env)
685{
Steve Block5baa3a62011-12-20 16:23:08 +0000686 //ALOGD("register_android_app_NativeActivity");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800687 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700688
Andreas Gampe987f79f2014-11-18 17:29:46 -0800689 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
690 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
691 "(II)V");
692 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
693 "(I)V");
694 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
695 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700696
Andreas Gampe987f79f2014-11-18 17:29:46 -0800697 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
Dianne Hackborn69969e42010-05-04 11:40:40 -0700698}
699
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700700} // namespace android