blob: 95be3f27b625a381a3a7818a0bdbadf3af4ac998 [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
Dianne Hackborn289b9b62010-07-09 11:44:11 -070024#include <android_runtime/android_app_NativeActivity.h>
Christopher Tate6cce32b2010-07-12 18:21:36 -070025#include <android_runtime/android_util_AssetManager.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080026#include <android_runtime/android_view_Surface.h>
27#include <android_runtime/AndroidRuntime.h>
Jeff Brown9d3b1a42013-07-01 19:07:15 -070028#include <input/InputTransport.h>
Mathias Agopian8335f1c2012-02-25 18:48:35 -080029
30#include <gui/Surface.h>
31
32#include <system/window.h>
33
Jeff Brown4fe6c3e2010-09-13 23:17:30 -070034#include <utils/Looper.h>
Dianne Hackborn69969e42010-05-04 11:40:40 -070035
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070036#include "JNIHelp.h"
37#include "android_os_MessageQueue.h"
38#include "android_view_InputChannel.h"
39#include "android_view_KeyEvent.h"
Dianne Hackborn69969e42010-05-04 11:40:40 -070040
Yong WU03c86602014-07-28 21:20:18 +080041#include "nativebridge/native_bridge.h"
42
Andreas Gampe987f79f2014-11-18 17:29:46 -080043#include "core_jni_helpers.h"
44
Andreas Gampeed6b9df2014-11-20 22:02:20 -080045
Dianne Hackborndb28a942010-10-21 17:22:30 -070046#define LOG_TRACE(...)
Steve Block28d9f022011-10-12 17:27:03 +010047//#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070048
Dianne Hackborn69969e42010-05-04 11:40:40 -070049namespace android
50{
51
Andreas Gampeed6b9df2014-11-20 22:02:20 -080052static const bool kLogTrace = false;
53
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070054static struct {
Dianne Hackborndb28a942010-10-21 17:22:30 -070055 jmethodID finish;
Dianne Hackborn54a181b2010-06-30 18:35:14 -070056 jmethodID setWindowFlags;
57 jmethodID setWindowFormat;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070058 jmethodID showIme;
59 jmethodID hideIme;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070060} gNativeActivityClassInfo;
61
Dianne Hackborn54a181b2010-06-30 18:35:14 -070062// ------------------------------------------------------------------------
63
Dianne Hackborn289b9b62010-07-09 11:44:11 -070064struct ActivityWork {
65 int32_t cmd;
66 int32_t arg1;
67 int32_t arg2;
68};
69
70enum {
Michael Wrighta44dd262013-04-10 21:12:00 -070071 CMD_FINISH = 1,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070072 CMD_SET_WINDOW_FORMAT,
73 CMD_SET_WINDOW_FLAGS,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070074 CMD_SHOW_SOFT_INPUT,
75 CMD_HIDE_SOFT_INPUT,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070076};
77
78static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
79 ActivityWork work;
80 work.cmd = cmd;
81 work.arg1 = arg1;
82 work.arg2 = arg2;
Andreas Gampeed6b9df2014-11-20 22:02:20 -080083
84 if (kLogTrace) {
85 ALOGD("write_work: cmd=%d", cmd);
86 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070087
Dianne Hackborn289b9b62010-07-09 11:44:11 -070088restart:
89 int res = write(fd, &work, sizeof(work));
90 if (res < 0 && errno == EINTR) {
91 goto restart;
92 }
93
94 if (res == sizeof(work)) return;
95
Steve Block8564c8d2012-01-05 23:22:43 +000096 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
97 else ALOGW("Truncated writing to work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -070098}
99
100static bool read_work(int fd, ActivityWork* outWork) {
101 int res = read(fd, outWork, sizeof(ActivityWork));
102 // no need to worry about EINTR, poll loop will just come back again.
103 if (res == sizeof(ActivityWork)) return true;
104
Steve Block8564c8d2012-01-05 23:22:43 +0000105 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
106 else ALOGW("Truncated reading work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700107 return false;
108}
109
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700110/*
111 * Native state for interacting with the NativeActivity class.
112 */
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700113struct NativeCode : public ANativeActivity {
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700114 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700115 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
116 memset(&callbacks, 0, sizeof(callbacks));
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700117 dlhandle = _dlhandle;
118 createActivityFunc = _createFunc;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700119 nativeWindow = NULL;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700120 mainWorkRead = mainWorkWrite = -1;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700121 }
122
123 ~NativeCode() {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700124 if (callbacks.onDestroy != NULL) {
125 callbacks.onDestroy(this);
126 }
127 if (env != NULL && clazz != NULL) {
128 env->DeleteGlobalRef(clazz);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700129 }
Jeff Brown603b4452012-04-06 17:39:41 -0700130 if (messageQueue != NULL && mainWorkRead >= 0) {
131 messageQueue->getLooper()->removeFd(mainWorkRead);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700132 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700133 setSurface(NULL);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700134 if (mainWorkRead >= 0) close(mainWorkRead);
135 if (mainWorkWrite >= 0) close(mainWorkWrite);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700136 if (dlhandle != NULL) {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700137 // for now don't unload... we probably should clean this
138 // up and only keep one open dlhandle per proc, since there
139 // is really no benefit to unloading the code.
140 //dlclose(dlhandle);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700141 }
142 }
143
144 void setSurface(jobject _surface) {
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700145 if (_surface != NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700146 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700147 } else {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700148 nativeWindow = NULL;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700149 }
150 }
151
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700152 ANativeActivityCallbacks callbacks;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700153
154 void* dlhandle;
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700155 ANativeActivity_createFunc* createActivityFunc;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700156
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800157 String8 internalDataPathObj;
158 String8 externalDataPathObj;
159 String8 obbPathObj;
Dianne Hackborn68267412010-07-02 18:52:01 -0700160
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700161 sp<ANativeWindow> nativeWindow;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700162 int32_t lastWindowWidth;
163 int32_t lastWindowHeight;
164
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700165 // These are used to wake up the main thread to process work.
166 int mainWorkRead;
167 int mainWorkWrite;
Jeff Brown603b4452012-04-06 17:39:41 -0700168 sp<MessageQueue> messageQueue;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700169};
170
Dianne Hackborndb28a942010-10-21 17:22:30 -0700171void android_NativeActivity_finish(ANativeActivity* activity) {
172 NativeCode* code = static_cast<NativeCode*>(activity);
173 write_work(code->mainWorkWrite, CMD_FINISH, 0);
174}
175
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700176void android_NativeActivity_setWindowFormat(
177 ANativeActivity* activity, int32_t format) {
178 NativeCode* code = static_cast<NativeCode*>(activity);
179 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
180}
181
182void android_NativeActivity_setWindowFlags(
183 ANativeActivity* activity, int32_t values, int32_t mask) {
184 NativeCode* code = static_cast<NativeCode*>(activity);
185 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
186}
187
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700188void android_NativeActivity_showSoftInput(
189 ANativeActivity* activity, int32_t flags) {
190 NativeCode* code = static_cast<NativeCode*>(activity);
191 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
192}
193
194void android_NativeActivity_hideSoftInput(
195 ANativeActivity* activity, int32_t flags) {
196 NativeCode* code = static_cast<NativeCode*>(activity);
197 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
198}
199
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700200// ------------------------------------------------------------------------
201
202/*
203 * Callback for handling native events on the application's main thread.
204 */
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700205static int mainWorkCallback(int fd, int events, void* data) {
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700206 NativeCode* code = (NativeCode*)data;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700207 if ((events & POLLIN) == 0) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700208 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700209 }
210
211 ActivityWork work;
212 if (!read_work(code->mainWorkRead, &work)) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700213 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700214 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700215
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800216 if (kLogTrace) {
217 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
218 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700219
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700220 switch (work.cmd) {
Dianne Hackborndb28a942010-10-21 17:22:30 -0700221 case CMD_FINISH: {
222 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
Jeff Brown603b4452012-04-06 17:39:41 -0700223 code->messageQueue->raiseAndClearException(code->env, "finish");
Dianne Hackborndb28a942010-10-21 17:22:30 -0700224 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700225 case CMD_SET_WINDOW_FORMAT: {
226 code->env->CallVoidMethod(code->clazz,
227 gNativeActivityClassInfo.setWindowFormat, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700228 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700229 } break;
230 case CMD_SET_WINDOW_FLAGS: {
231 code->env->CallVoidMethod(code->clazz,
232 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
Jeff Brown603b4452012-04-06 17:39:41 -0700233 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700234 } break;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700235 case CMD_SHOW_SOFT_INPUT: {
236 code->env->CallVoidMethod(code->clazz,
237 gNativeActivityClassInfo.showIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700238 code->messageQueue->raiseAndClearException(code->env, "showIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700239 } break;
240 case CMD_HIDE_SOFT_INPUT: {
241 code->env->CallVoidMethod(code->clazz,
242 gNativeActivityClassInfo.hideIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700243 code->messageQueue->raiseAndClearException(code->env, "hideIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700244 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700245 default:
Steve Block8564c8d2012-01-05 23:22:43 +0000246 ALOGW("Unknown work command: %d", work.cmd);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700247 break;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700248 }
249
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700250 return 1;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700251}
252
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700253// ------------------------------------------------------------------------
254
Ashok Bhat58b8b242014-01-02 16:52:41 +0000255static jlong
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700256loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800257 jobject messageQueue, jstring internalDataDir, jstring obbDir,
Ashok Bhat58b8b242014-01-02 16:52:41 +0000258 jstring externalDataDir, jint sdkVersion,
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700259 jobject jAssetMgr, jbyteArray savedState)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700260{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800261 if (kLogTrace) {
262 ALOGD("loadNativeCode_native");
263 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700264
Dianne Hackborn69969e42010-05-04 11:40:40 -0700265 const char* pathStr = env->GetStringUTFChars(path, NULL);
266 NativeCode* code = NULL;
Yong WU03c86602014-07-28 21:20:18 +0800267 bool needNativeBridge = false;
268
Dianne Hackborn69969e42010-05-04 11:40:40 -0700269 void* handle = dlopen(pathStr, RTLD_LAZY);
Yong WU03c86602014-07-28 21:20:18 +0800270 if (handle == NULL) {
271 if (NativeBridgeIsSupported(pathStr)) {
272 handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
273 needNativeBridge = true;
274 }
275 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700276 env->ReleaseStringUTFChars(path, pathStr);
Yong WU03c86602014-07-28 21:20:18 +0800277
Dianne Hackborn69969e42010-05-04 11:40:40 -0700278 if (handle != NULL) {
Yong WU03c86602014-07-28 21:20:18 +0800279 void* funcPtr = NULL;
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700280 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
Yong WU03c86602014-07-28 21:20:18 +0800281 if (needNativeBridge) {
282 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
283 } else {
284 funcPtr = dlsym(handle, funcStr);
285 }
286
287 code = new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr);
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700288 env->ReleaseStringUTFChars(funcName, funcStr);
Yong WU03c86602014-07-28 21:20:18 +0800289
Dianne Hackborn69969e42010-05-04 11:40:40 -0700290 if (code->createActivityFunc == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000291 ALOGW("ANativeActivity_onCreate not found");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700292 delete code;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700293 return 0;
294 }
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700295
Jeff Brown603b4452012-04-06 17:39:41 -0700296 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
297 if (code->messageQueue == NULL) {
298 ALOGW("Unable to retrieve native MessageQueue");
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700299 delete code;
300 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 delete code;
307 return 0;
308 }
309 code->mainWorkRead = msgpipe[0];
310 code->mainWorkWrite = msgpipe[1];
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700311 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
312 SLOGW_IF(result != 0, "Could not make main work read pipe "
313 "non-blocking: %s", strerror(errno));
314 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
315 SLOGW_IF(result != 0, "Could not make main work write pipe "
316 "non-blocking: %s", strerror(errno));
Jeff Brown603b4452012-04-06 17:39:41 -0700317 code->messageQueue->getLooper()->addFd(
318 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700319
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700320 code->ANativeActivity::callbacks = &code->callbacks;
321 if (env->GetJavaVM(&code->vm) < 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000322 ALOGW("NativeActivity GetJavaVM failed");
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700323 delete code;
324 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
359 code->createActivityFunc(code, rawSavedState, rawSavedSize);
360
361 if (rawSavedState != NULL) {
362 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
363 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700364 }
365
Ashok Bhat58b8b242014-01-02 16:52:41 +0000366 return (jlong)code;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700367}
368
369static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000370unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700371{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800372 if (kLogTrace) {
373 ALOGD("unloadNativeCode_native");
374 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700375 if (handle != 0) {
376 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700377 delete code;
378 }
379}
380
381static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000382onStart_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700383{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800384 if (kLogTrace) {
385 ALOGD("onStart_native");
386 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700387 if (handle != 0) {
388 NativeCode* code = (NativeCode*)handle;
389 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700390 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700391 }
392 }
393}
394
395static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000396onResume_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700397{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800398 if (kLogTrace) {
399 ALOGD("onResume_native");
400 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700401 if (handle != 0) {
402 NativeCode* code = (NativeCode*)handle;
403 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700404 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700405 }
406 }
407}
408
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700409static jbyteArray
Ashok Bhat58b8b242014-01-02 16:52:41 +0000410onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700411{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800412 if (kLogTrace) {
413 ALOGD("onSaveInstanceState_native");
414 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700415
416 jbyteArray array = NULL;
417
Dianne Hackborn69969e42010-05-04 11:40:40 -0700418 if (handle != 0) {
419 NativeCode* code = (NativeCode*)handle;
420 if (code->callbacks.onSaveInstanceState != NULL) {
421 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700422 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
423 if (len > 0) {
424 array = env->NewByteArray(len);
425 if (array != NULL) {
426 env->SetByteArrayRegion(array, 0, len, state);
427 }
428 }
429 if (state != NULL) {
430 free(state);
431 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700432 }
433 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700434
435 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700436}
437
438static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000439onPause_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700440{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800441 if (kLogTrace) {
442 ALOGD("onPause_native");
443 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700444 if (handle != 0) {
445 NativeCode* code = (NativeCode*)handle;
446 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700447 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700448 }
449 }
450}
451
452static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000453onStop_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700454{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800455 if (kLogTrace) {
456 ALOGD("onStop_native");
457 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700458 if (handle != 0) {
459 NativeCode* code = (NativeCode*)handle;
460 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700461 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700462 }
463 }
464}
465
466static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000467onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700468{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800469 if (kLogTrace) {
470 ALOGD("onConfigurationChanged_native");
471 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700472 if (handle != 0) {
473 NativeCode* code = (NativeCode*)handle;
474 if (code->callbacks.onConfigurationChanged != NULL) {
475 code->callbacks.onConfigurationChanged(code);
476 }
477 }
478}
479
480static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000481onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700482{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800483 if (kLogTrace) {
484 ALOGD("onLowMemory_native");
485 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700486 if (handle != 0) {
487 NativeCode* code = (NativeCode*)handle;
488 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700489 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700490 }
491 }
492}
493
494static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000495onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700496{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800497 if (kLogTrace) {
498 ALOGD("onWindowFocusChanged_native");
499 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700500 if (handle != 0) {
501 NativeCode* code = (NativeCode*)handle;
502 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700503 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700504 }
505 }
506}
507
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700508static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000509onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700510{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800511 if (kLogTrace) {
512 ALOGD("onSurfaceCreated_native");
513 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700514 if (handle != 0) {
515 NativeCode* code = (NativeCode*)handle;
516 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700517 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700518 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700519 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700520 }
521 }
522}
523
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700524static int32_t getWindowProp(ANativeWindow* window, int what) {
525 int value;
526 int res = window->query(window, what, &value);
527 return res < 0 ? res : value;
528}
529
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700530static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000531onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700532 jint format, jint width, jint height)
533{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800534 if (kLogTrace) {
535 ALOGD("onSurfaceChanged_native");
536 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700537 if (handle != 0) {
538 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700539 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
540 code->setSurface(surface);
541 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700542 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700543 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700544 oldNativeWindow.get());
545 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700546 if (code->nativeWindow != NULL) {
547 if (code->callbacks.onNativeWindowCreated != NULL) {
548 code->callbacks.onNativeWindowCreated(code,
549 code->nativeWindow.get());
550 }
551 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
552 NATIVE_WINDOW_WIDTH);
553 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
554 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700555 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700556 } else {
557 // Maybe it resized?
558 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
559 NATIVE_WINDOW_WIDTH);
560 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
561 NATIVE_WINDOW_HEIGHT);
562 if (newWidth != code->lastWindowWidth
563 || newHeight != code->lastWindowHeight) {
564 if (code->callbacks.onNativeWindowResized != NULL) {
565 code->callbacks.onNativeWindowResized(code,
566 code->nativeWindow.get());
567 }
568 }
569 }
570 }
571}
572
573static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000574onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700575{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800576 if (kLogTrace) {
577 ALOGD("onSurfaceRedrawNeeded_native");
578 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700579 if (handle != 0) {
580 NativeCode* code = (NativeCode*)handle;
581 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
582 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700583 }
584 }
585}
586
587static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000588onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700589{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800590 if (kLogTrace) {
591 ALOGD("onSurfaceDestroyed_native");
592 }
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700593 if (handle != 0) {
594 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700595 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700596 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700597 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700598 }
599 code->setSurface(NULL);
600 }
601}
602
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700603static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000604onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700605{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800606 if (kLogTrace) {
607 ALOGD("onInputChannelCreated_native");
608 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700609 if (handle != 0) {
610 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700611 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700612 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
613 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700614 }
615 }
616}
617
618static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000619onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700620{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800621 if (kLogTrace) {
622 ALOGD("onInputChannelDestroyed_native");
623 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700624 if (handle != 0) {
625 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700626 if (code->callbacks.onInputQueueDestroyed != NULL) {
627 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
628 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700629 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700630 }
631}
632
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700633static void
Ashok Bhat58b8b242014-01-02 16:52:41 +0000634onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700635 jint x, jint y, jint w, jint h)
636{
Andreas Gampeed6b9df2014-11-20 22:02:20 -0800637 if (kLogTrace) {
638 ALOGD("onContentRectChanged_native");
639 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700640 if (handle != 0) {
641 NativeCode* code = (NativeCode*)handle;
642 if (code->callbacks.onContentRectChanged != NULL) {
643 ARect rect;
644 rect.left = x;
645 rect.top = y;
646 rect.right = x+w;
647 rect.bottom = y+h;
648 code->callbacks.onContentRectChanged(code, &rect);
649 }
650 }
651}
652
Dianne Hackborn69969e42010-05-04 11:40:40 -0700653static const JNINativeMethod g_methods[] = {
Ashok Bhat58b8b242014-01-02 16:52:41 +0000654 { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)J",
Dianne Hackborn68267412010-07-02 18:52:01 -0700655 (void*)loadNativeCode_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000656 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
657 { "onStartNative", "(J)V", (void*)onStart_native },
658 { "onResumeNative", "(J)V", (void*)onResume_native },
659 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
660 { "onPauseNative", "(J)V", (void*)onPause_native },
661 { "onStopNative", "(J)V", (void*)onStop_native },
662 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
663 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
664 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
665 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
666 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
667 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
668 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
669 { "onInputQueueCreatedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700670 (void*)onInputQueueCreated_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000671 { "onInputQueueDestroyedNative", "(JJ)V",
Michael Wrighta44dd262013-04-10 21:12:00 -0700672 (void*)onInputQueueDestroyed_native },
Ashok Bhat58b8b242014-01-02 16:52:41 +0000673 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700674};
675
676static const char* const kNativeActivityPathName = "android/app/NativeActivity";
677
678int register_android_app_NativeActivity(JNIEnv* env)
679{
Steve Block5baa3a62011-12-20 16:23:08 +0000680 //ALOGD("register_android_app_NativeActivity");
Andreas Gampe987f79f2014-11-18 17:29:46 -0800681 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700682
Andreas Gampe987f79f2014-11-18 17:29:46 -0800683 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
684 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
685 "(II)V");
686 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
687 "(I)V");
688 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
689 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700690
Andreas Gampe987f79f2014-11-18 17:29:46 -0800691 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
Dianne Hackborn69969e42010-05-04 11:40:40 -0700692}
693
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700694} // namespace android