blob: 6431b94be4d3d8bad43da4527aa00a87c71b60a9 [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,
Dimitry Ivanova55c7f12016-02-23 14:25:50 -0800262 jbyteArray savedState, jobject classLoader, jstring libraryPath) {
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800263 if (kLogTrace) {
264 ALOGD("loadNativeCode_native");
265 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700266
Dianne Hackborn69969e42010-05-04 11:40:40 -0700267 const char* pathStr = env->GetStringUTFChars(path, NULL);
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800268 std::unique_ptr<NativeCode> code;
Yong WU03c86602014-07-28 21:20:18 +0800269 bool needNativeBridge = false;
270
Dimitry Ivanova55c7f12016-02-23 14:25:50 -0800271 void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader, libraryPath);
Yong WU03c86602014-07-28 21:20:18 +0800272 if (handle == NULL) {
273 if (NativeBridgeIsSupported(pathStr)) {
274 handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
275 needNativeBridge = true;
276 }
277 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700278 env->ReleaseStringUTFChars(path, pathStr);
Yong WU03c86602014-07-28 21:20:18 +0800279
Dianne Hackborn69969e42010-05-04 11:40:40 -0700280 if (handle != NULL) {
Yong WU03c86602014-07-28 21:20:18 +0800281 void* funcPtr = NULL;
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700282 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
Yong WU03c86602014-07-28 21:20:18 +0800283 if (needNativeBridge) {
284 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
285 } else {
286 funcPtr = dlsym(handle, funcStr);
287 }
288
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800289 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700290 env->ReleaseStringUTFChars(funcName, funcStr);
Yong WU03c86602014-07-28 21:20:18 +0800291
Dianne Hackborn69969e42010-05-04 11:40:40 -0700292 if (code->createActivityFunc == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000293 ALOGW("ANativeActivity_onCreate not found");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700294 return 0;
295 }
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700296
Jeff Brown603b4452012-04-06 17:39:41 -0700297 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
298 if (code->messageQueue == NULL) {
299 ALOGW("Unable to retrieve native MessageQueue");
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700300 return 0;
301 }
302
303 int msgpipe[2];
304 if (pipe(msgpipe)) {
Steve Block8564c8d2012-01-05 23:22:43 +0000305 ALOGW("could not create pipe: %s", strerror(errno));
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700306 return 0;
307 }
308 code->mainWorkRead = msgpipe[0];
309 code->mainWorkWrite = msgpipe[1];
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700310 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
311 SLOGW_IF(result != 0, "Could not make main work read pipe "
312 "non-blocking: %s", strerror(errno));
313 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
314 SLOGW_IF(result != 0, "Could not make main work write pipe "
315 "non-blocking: %s", strerror(errno));
Jeff Brown603b4452012-04-06 17:39:41 -0700316 code->messageQueue->getLooper()->addFd(
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800317 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700318
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700319 code->ANativeActivity::callbacks = &code->callbacks;
320 if (env->GetJavaVM(&code->vm) < 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000321 ALOGW("NativeActivity GetJavaVM failed");
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700322 return 0;
323 }
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700324 code->env = env;
325 code->clazz = env->NewGlobalRef(clazz);
Christopher Tate6cce32b2010-07-12 18:21:36 -0700326
Dianne Hackborn68267412010-07-02 18:52:01 -0700327 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800328 code->internalDataPathObj = dirStr;
329 code->internalDataPath = code->internalDataPathObj.string();
330 env->ReleaseStringUTFChars(internalDataDir, dirStr);
Dianne Hackborn68267412010-07-02 18:52:01 -0700331
Jeff Sharkeye0475c82013-08-15 11:50:02 -0700332 if (externalDataDir != NULL) {
333 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
334 code->externalDataPathObj = dirStr;
335 env->ReleaseStringUTFChars(externalDataDir, dirStr);
336 }
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800337 code->externalDataPath = code->externalDataPathObj.string();
Christopher Tate6cce32b2010-07-12 18:21:36 -0700338
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700339 code->sdkVersion = sdkVersion;
Dianne Hackborn68267412010-07-02 18:52:01 -0700340
Christopher Tate6cce32b2010-07-12 18:21:36 -0700341 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
342
Jeff Sharkeye0475c82013-08-15 11:50:02 -0700343 if (obbDir != NULL) {
344 dirStr = env->GetStringUTFChars(obbDir, NULL);
345 code->obbPathObj = dirStr;
346 env->ReleaseStringUTFChars(obbDir, dirStr);
347 }
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800348 code->obbPath = code->obbPathObj.string();
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800349
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700350 jbyte* rawSavedState = NULL;
351 jsize rawSavedSize = 0;
352 if (savedState != NULL) {
353 rawSavedState = env->GetByteArrayElements(savedState, NULL);
354 rawSavedSize = env->GetArrayLength(savedState);
355 }
356
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800357 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700358
359 if (rawSavedState != NULL) {
360 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
361 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700362 }
363
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800364 return (jlong)code.release();
365}
366
367static jstring getDlError_native(JNIEnv* env, jobject clazz) {
368 return env->NewStringUTF(dlerror());
Dianne Hackborn69969e42010-05-04 11:40:40 -0700369}
370
371static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000372unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700373{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800374 if (kLogTrace) {
375 ALOGD("unloadNativeCode_native");
376 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700377 if (handle != 0) {
378 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700379 delete code;
380 }
381}
382
383static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000384onStart_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700385{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800386 if (kLogTrace) {
387 ALOGD("onStart_native");
388 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700389 if (handle != 0) {
390 NativeCode* code = (NativeCode*)handle;
391 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700392 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700393 }
394 }
395}
396
397static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000398onResume_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700399{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800400 if (kLogTrace) {
401 ALOGD("onResume_native");
402 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700403 if (handle != 0) {
404 NativeCode* code = (NativeCode*)handle;
405 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700406 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700407 }
408 }
409}
410
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700411static jbyteArray
Ashok Bhat58b8b242014-01-02 16:52:41 +0000412onSaveInstanceState_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("onSaveInstanceState_native");
416 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700417
418 jbyteArray array = NULL;
419
Dianne Hackborn69969e42010-05-04 11:40:40 -0700420 if (handle != 0) {
421 NativeCode* code = (NativeCode*)handle;
422 if (code->callbacks.onSaveInstanceState != NULL) {
423 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700424 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
425 if (len > 0) {
426 array = env->NewByteArray(len);
427 if (array != NULL) {
428 env->SetByteArrayRegion(array, 0, len, state);
429 }
430 }
431 if (state != NULL) {
432 free(state);
433 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700434 }
435 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700436
437 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700438}
439
440static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000441onPause_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700442{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800443 if (kLogTrace) {
444 ALOGD("onPause_native");
445 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700446 if (handle != 0) {
447 NativeCode* code = (NativeCode*)handle;
448 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700449 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700450 }
451 }
452}
453
454static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000455onStop_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700456{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800457 if (kLogTrace) {
458 ALOGD("onStop_native");
459 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700460 if (handle != 0) {
461 NativeCode* code = (NativeCode*)handle;
462 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700463 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700464 }
465 }
466}
467
468static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000469onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700470{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800471 if (kLogTrace) {
472 ALOGD("onConfigurationChanged_native");
473 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700474 if (handle != 0) {
475 NativeCode* code = (NativeCode*)handle;
476 if (code->callbacks.onConfigurationChanged != NULL) {
477 code->callbacks.onConfigurationChanged(code);
478 }
479 }
480}
481
482static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000483onLowMemory_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("onLowMemory_native");
487 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700488 if (handle != 0) {
489 NativeCode* code = (NativeCode*)handle;
490 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700491 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700492 }
493 }
494}
495
496static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000497onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700498{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800499 if (kLogTrace) {
500 ALOGD("onWindowFocusChanged_native");
501 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700502 if (handle != 0) {
503 NativeCode* code = (NativeCode*)handle;
504 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700505 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700506 }
507 }
508}
509
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700510static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000511onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700512{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800513 if (kLogTrace) {
514 ALOGD("onSurfaceCreated_native");
515 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700516 if (handle != 0) {
517 NativeCode* code = (NativeCode*)handle;
518 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700519 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700520 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700521 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700522 }
523 }
524}
525
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700526static int32_t getWindowProp(ANativeWindow* window, int what) {
527 int value;
528 int res = window->query(window, what, &value);
529 return res < 0 ? res : value;
530}
531
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700532static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000533onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700534 jint format, jint width, jint height)
535{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800536 if (kLogTrace) {
537 ALOGD("onSurfaceChanged_native");
538 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700539 if (handle != 0) {
540 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700541 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
542 code->setSurface(surface);
543 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700544 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700545 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700546 oldNativeWindow.get());
547 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700548 if (code->nativeWindow != NULL) {
549 if (code->callbacks.onNativeWindowCreated != NULL) {
550 code->callbacks.onNativeWindowCreated(code,
551 code->nativeWindow.get());
552 }
553 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
554 NATIVE_WINDOW_WIDTH);
555 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
556 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700557 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700558 } else {
559 // Maybe it resized?
560 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
561 NATIVE_WINDOW_WIDTH);
562 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
563 NATIVE_WINDOW_HEIGHT);
564 if (newWidth != code->lastWindowWidth
565 || newHeight != code->lastWindowHeight) {
566 if (code->callbacks.onNativeWindowResized != NULL) {
567 code->callbacks.onNativeWindowResized(code,
568 code->nativeWindow.get());
569 }
570 }
571 }
572 }
573}
574
575static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000576onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700577{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800578 if (kLogTrace) {
579 ALOGD("onSurfaceRedrawNeeded_native");
580 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700581 if (handle != 0) {
582 NativeCode* code = (NativeCode*)handle;
583 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
584 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700585 }
586 }
587}
588
589static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000590onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700591{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800592 if (kLogTrace) {
593 ALOGD("onSurfaceDestroyed_native");
594 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700595 if (handle != 0) {
596 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700597 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700598 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700599 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700600 }
601 code->setSurface(NULL);
602 }
603}
604
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700605static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000606onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700607{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800608 if (kLogTrace) {
609 ALOGD("onInputChannelCreated_native");
610 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700611 if (handle != 0) {
612 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700613 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700614 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
615 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700616 }
617 }
618}
619
620static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000621onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700622{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800623 if (kLogTrace) {
624 ALOGD("onInputChannelDestroyed_native");
625 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700626 if (handle != 0) {
627 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700628 if (code->callbacks.onInputQueueDestroyed != NULL) {
629 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
630 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700631 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700632 }
633}
634
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700635static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000636onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700637 jint x, jint y, jint w, jint h)
638{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800639 if (kLogTrace) {
640 ALOGD("onContentRectChanged_native");
641 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700642 if (handle != 0) {
643 NativeCode* code = (NativeCode*)handle;
644 if (code->callbacks.onContentRectChanged != NULL) {
645 ARect rect;
646 rect.left = x;
647 rect.top = y;
648 rect.right = x+w;
649 rect.bottom = y+h;
650 code->callbacks.onContentRectChanged(code, &rect);
651 }
652 }
653}
654
Dianne Hackborn69969e42010-05-04 11:40:40 -0700655static const JNINativeMethod g_methods[] = {
Dmitriy Ivanov048a0db2015-11-15 14:58:36 -0800656 { "loadNativeCode",
Dimitry Ivanova55c7f12016-02-23 14:25:50 -0800657 "(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 Ivanov048a0db2015-11-15 14:58:36 -0800658 (void*)loadNativeCode_native },
659 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000660 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
661 { "onStartNative", "(J)V", (void*)onStart_native },
662 { "onResumeNative", "(J)V", (void*)onResume_native },
663 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
664 { "onPauseNative", "(J)V", (void*)onPause_native },
665 { "onStopNative", "(J)V", (void*)onStop_native },
666 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
667 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
668 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
669 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
670 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
671 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
672 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
673 { "onInputQueueCreatedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700674 (void*)onInputQueueCreated_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000675 { "onInputQueueDestroyedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700676 (void*)onInputQueueDestroyed_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000677 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700678};
679
680static const char* const kNativeActivityPathName = "android/app/NativeActivity";
681
682int register_android_app_NativeActivity(JNIEnv* env)
683{
Steve Block5baa3a62011-12-20 16:23:08 +0000684 //ALOGD("register_android_app_NativeActivity");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800685 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700686
Andreas Gampe987f79f2014-11-18 17:29:46 -0800687 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
688 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
689 "(II)V");
690 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
691 "(I)V");
692 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
693 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700694
Andreas Gampe987f79f2014-11-18 17:29:46 -0800695 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
Dianne Hackborn69969e42010-05-04 11:40:40 -0700696}
697
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700698} // namespace android