blob: 9fc01e1adcd7fc4b82bc01ba286bb8ca491300e5 [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>
Mathias Agopianb93a03f82012-02-17 15:34:57 -080028#include <androidfw/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
Dianne Hackborndb28a942010-10-21 17:22:30 -070041#define LOG_TRACE(...)
Steve Block28d9f022011-10-12 17:27:03 +010042//#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070043
Dianne Hackborn69969e42010-05-04 11:40:40 -070044namespace android
45{
46
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070047static struct {
Dianne Hackborndb28a942010-10-21 17:22:30 -070048 jmethodID finish;
Dianne Hackborn54a181b2010-06-30 18:35:14 -070049 jmethodID setWindowFlags;
50 jmethodID setWindowFormat;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070051 jmethodID showIme;
52 jmethodID hideIme;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -070053} gNativeActivityClassInfo;
54
Dianne Hackborn54a181b2010-06-30 18:35:14 -070055// ------------------------------------------------------------------------
56
Dianne Hackborn289b9b62010-07-09 11:44:11 -070057struct ActivityWork {
58 int32_t cmd;
59 int32_t arg1;
60 int32_t arg2;
61};
62
63enum {
Michael Wrighta44dd262013-04-10 21:12:00 -070064 CMD_FINISH = 1,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070065 CMD_SET_WINDOW_FORMAT,
66 CMD_SET_WINDOW_FLAGS,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070067 CMD_SHOW_SOFT_INPUT,
68 CMD_HIDE_SOFT_INPUT,
Dianne Hackborn289b9b62010-07-09 11:44:11 -070069};
70
71static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
72 ActivityWork work;
73 work.cmd = cmd;
74 work.arg1 = arg1;
75 work.arg2 = arg2;
76
Dianne Hackbornd76b67c2010-07-13 17:48:30 -070077 LOG_TRACE("write_work: cmd=%d", cmd);
78
Dianne Hackborn289b9b62010-07-09 11:44:11 -070079restart:
80 int res = write(fd, &work, sizeof(work));
81 if (res < 0 && errno == EINTR) {
82 goto restart;
83 }
84
85 if (res == sizeof(work)) return;
86
Steve Block8564c8d2012-01-05 23:22:43 +000087 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
88 else ALOGW("Truncated writing to work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -070089}
90
91static bool read_work(int fd, ActivityWork* outWork) {
92 int res = read(fd, outWork, sizeof(ActivityWork));
93 // no need to worry about EINTR, poll loop will just come back again.
94 if (res == sizeof(ActivityWork)) return true;
95
Steve Block8564c8d2012-01-05 23:22:43 +000096 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
97 else ALOGW("Truncated reading work fd: %d", res);
Dianne Hackborn289b9b62010-07-09 11:44:11 -070098 return false;
99}
100
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700101/*
102 * Native state for interacting with the NativeActivity class.
103 */
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700104struct NativeCode : public ANativeActivity {
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700105 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700106 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
107 memset(&callbacks, 0, sizeof(callbacks));
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700108 dlhandle = _dlhandle;
109 createActivityFunc = _createFunc;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700110 nativeWindow = NULL;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700111 mainWorkRead = mainWorkWrite = -1;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700112 }
113
114 ~NativeCode() {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700115 if (callbacks.onDestroy != NULL) {
116 callbacks.onDestroy(this);
117 }
118 if (env != NULL && clazz != NULL) {
119 env->DeleteGlobalRef(clazz);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700120 }
Jeff Brown603b4452012-04-06 17:39:41 -0700121 if (messageQueue != NULL && mainWorkRead >= 0) {
122 messageQueue->getLooper()->removeFd(mainWorkRead);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700123 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700124 setSurface(NULL);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700125 if (mainWorkRead >= 0) close(mainWorkRead);
126 if (mainWorkWrite >= 0) close(mainWorkWrite);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700127 if (dlhandle != NULL) {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700128 // for now don't unload... we probably should clean this
129 // up and only keep one open dlhandle per proc, since there
130 // is really no benefit to unloading the code.
131 //dlclose(dlhandle);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700132 }
133 }
134
135 void setSurface(jobject _surface) {
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700136 if (_surface != NULL) {
Jeff Brown64a55af2012-08-26 02:47:39 -0700137 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700138 } else {
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700139 nativeWindow = NULL;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700140 }
141 }
142
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700143 ANativeActivityCallbacks callbacks;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700144
145 void* dlhandle;
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700146 ANativeActivity_createFunc* createActivityFunc;
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700147
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800148 String8 internalDataPathObj;
149 String8 externalDataPathObj;
150 String8 obbPathObj;
Dianne Hackborn68267412010-07-02 18:52:01 -0700151
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700152 sp<ANativeWindow> nativeWindow;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700153 int32_t lastWindowWidth;
154 int32_t lastWindowHeight;
155
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700156 // These are used to wake up the main thread to process work.
157 int mainWorkRead;
158 int mainWorkWrite;
Jeff Brown603b4452012-04-06 17:39:41 -0700159 sp<MessageQueue> messageQueue;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700160};
161
Dianne Hackborndb28a942010-10-21 17:22:30 -0700162void android_NativeActivity_finish(ANativeActivity* activity) {
163 NativeCode* code = static_cast<NativeCode*>(activity);
164 write_work(code->mainWorkWrite, CMD_FINISH, 0);
165}
166
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700167void android_NativeActivity_setWindowFormat(
168 ANativeActivity* activity, int32_t format) {
169 NativeCode* code = static_cast<NativeCode*>(activity);
170 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
171}
172
173void android_NativeActivity_setWindowFlags(
174 ANativeActivity* activity, int32_t values, int32_t mask) {
175 NativeCode* code = static_cast<NativeCode*>(activity);
176 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
177}
178
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700179void android_NativeActivity_showSoftInput(
180 ANativeActivity* activity, int32_t flags) {
181 NativeCode* code = static_cast<NativeCode*>(activity);
182 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
183}
184
185void android_NativeActivity_hideSoftInput(
186 ANativeActivity* activity, int32_t flags) {
187 NativeCode* code = static_cast<NativeCode*>(activity);
188 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
189}
190
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700191// ------------------------------------------------------------------------
192
193/*
194 * Callback for handling native events on the application's main thread.
195 */
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700196static int mainWorkCallback(int fd, int events, void* data) {
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700197 NativeCode* code = (NativeCode*)data;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700198 if ((events & POLLIN) == 0) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700199 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700200 }
201
202 ActivityWork work;
203 if (!read_work(code->mainWorkRead, &work)) {
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700204 return 1;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700205 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700206
207 LOG_TRACE("mainWorkCallback: cmd=%d", work.cmd);
208
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700209 switch (work.cmd) {
Dianne Hackborndb28a942010-10-21 17:22:30 -0700210 case CMD_FINISH: {
211 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
Jeff Brown603b4452012-04-06 17:39:41 -0700212 code->messageQueue->raiseAndClearException(code->env, "finish");
Dianne Hackborndb28a942010-10-21 17:22:30 -0700213 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700214 case CMD_SET_WINDOW_FORMAT: {
215 code->env->CallVoidMethod(code->clazz,
216 gNativeActivityClassInfo.setWindowFormat, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700217 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700218 } break;
219 case CMD_SET_WINDOW_FLAGS: {
220 code->env->CallVoidMethod(code->clazz,
221 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
Jeff Brown603b4452012-04-06 17:39:41 -0700222 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700223 } break;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700224 case CMD_SHOW_SOFT_INPUT: {
225 code->env->CallVoidMethod(code->clazz,
226 gNativeActivityClassInfo.showIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700227 code->messageQueue->raiseAndClearException(code->env, "showIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700228 } break;
229 case CMD_HIDE_SOFT_INPUT: {
230 code->env->CallVoidMethod(code->clazz,
231 gNativeActivityClassInfo.hideIme, work.arg1);
Jeff Brown603b4452012-04-06 17:39:41 -0700232 code->messageQueue->raiseAndClearException(code->env, "hideIme");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700233 } break;
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700234 default:
Steve Block8564c8d2012-01-05 23:22:43 +0000235 ALOGW("Unknown work command: %d", work.cmd);
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700236 break;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700237 }
238
Jeff Brown4fe6c3e2010-09-13 23:17:30 -0700239 return 1;
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700240}
241
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700242// ------------------------------------------------------------------------
243
Dianne Hackborn69969e42010-05-04 11:40:40 -0700244static jint
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700245loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800246 jobject messageQueue, jstring internalDataDir, jstring obbDir,
247 jstring externalDataDir, int sdkVersion,
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700248 jobject jAssetMgr, jbyteArray savedState)
Dianne Hackborn69969e42010-05-04 11:40:40 -0700249{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700250 LOG_TRACE("loadNativeCode_native");
251
Dianne Hackborn69969e42010-05-04 11:40:40 -0700252 const char* pathStr = env->GetStringUTFChars(path, NULL);
253 NativeCode* code = NULL;
254
255 void* handle = dlopen(pathStr, RTLD_LAZY);
256
257 env->ReleaseStringUTFChars(path, pathStr);
258
259 if (handle != NULL) {
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700260 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700261 code = new NativeCode(handle, (ANativeActivity_createFunc*)
Dianne Hackborne21d91c62010-10-24 14:56:38 -0700262 dlsym(handle, funcStr));
263 env->ReleaseStringUTFChars(funcName, funcStr);
264
Dianne Hackborn69969e42010-05-04 11:40:40 -0700265 if (code->createActivityFunc == NULL) {
Steve Block8564c8d2012-01-05 23:22:43 +0000266 ALOGW("ANativeActivity_onCreate not found");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700267 delete code;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700268 return 0;
269 }
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700270
Jeff Brown603b4452012-04-06 17:39:41 -0700271 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
272 if (code->messageQueue == NULL) {
273 ALOGW("Unable to retrieve native MessageQueue");
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700274 delete code;
275 return 0;
276 }
277
278 int msgpipe[2];
279 if (pipe(msgpipe)) {
Steve Block8564c8d2012-01-05 23:22:43 +0000280 ALOGW("could not create pipe: %s", strerror(errno));
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700281 delete code;
282 return 0;
283 }
284 code->mainWorkRead = msgpipe[0];
285 code->mainWorkWrite = msgpipe[1];
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700286 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
287 SLOGW_IF(result != 0, "Could not make main work read pipe "
288 "non-blocking: %s", strerror(errno));
289 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
290 SLOGW_IF(result != 0, "Could not make main work write pipe "
291 "non-blocking: %s", strerror(errno));
Jeff Brown603b4452012-04-06 17:39:41 -0700292 code->messageQueue->getLooper()->addFd(
293 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700294
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700295 code->ANativeActivity::callbacks = &code->callbacks;
296 if (env->GetJavaVM(&code->vm) < 0) {
Steve Block8564c8d2012-01-05 23:22:43 +0000297 ALOGW("NativeActivity GetJavaVM failed");
Dianne Hackborn2e9f93e2010-06-28 15:27:30 -0700298 delete code;
299 return 0;
300 }
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700301 code->env = env;
302 code->clazz = env->NewGlobalRef(clazz);
Christopher Tate6cce32b2010-07-12 18:21:36 -0700303
Dianne Hackborn68267412010-07-02 18:52:01 -0700304 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800305 code->internalDataPathObj = dirStr;
306 code->internalDataPath = code->internalDataPathObj.string();
307 env->ReleaseStringUTFChars(internalDataDir, dirStr);
Dianne Hackborn68267412010-07-02 18:52:01 -0700308
309 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800310 code->externalDataPathObj = dirStr;
311 code->externalDataPath = code->externalDataPathObj.string();
312 env->ReleaseStringUTFChars(externalDataDir, dirStr);
Christopher Tate6cce32b2010-07-12 18:21:36 -0700313
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700314 code->sdkVersion = sdkVersion;
Dianne Hackborn68267412010-07-02 18:52:01 -0700315
Christopher Tate6cce32b2010-07-12 18:21:36 -0700316 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
317
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800318 dirStr = env->GetStringUTFChars(obbDir, NULL);
319 code->obbPathObj = dirStr;
320 code->obbPath = code->obbPathObj.string();
321 env->ReleaseStringUTFChars(obbDir, dirStr);
322
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700323 jbyte* rawSavedState = NULL;
324 jsize rawSavedSize = 0;
325 if (savedState != NULL) {
326 rawSavedState = env->GetByteArrayElements(savedState, NULL);
327 rawSavedSize = env->GetArrayLength(savedState);
328 }
329
330 code->createActivityFunc(code, rawSavedState, rawSavedSize);
331
332 if (rawSavedState != NULL) {
333 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
334 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700335 }
336
337 return (jint)code;
338}
339
340static void
341unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle)
342{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700343 LOG_TRACE("unloadNativeCode_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700344 if (handle != 0) {
345 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700346 delete code;
347 }
348}
349
350static void
351onStart_native(JNIEnv* env, jobject clazz, jint handle)
352{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700353 LOG_TRACE("onStart_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700354 if (handle != 0) {
355 NativeCode* code = (NativeCode*)handle;
356 if (code->callbacks.onStart != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700357 code->callbacks.onStart(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700358 }
359 }
360}
361
362static void
363onResume_native(JNIEnv* env, jobject clazz, jint handle)
364{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700365 LOG_TRACE("onResume_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700366 if (handle != 0) {
367 NativeCode* code = (NativeCode*)handle;
368 if (code->callbacks.onResume != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700369 code->callbacks.onResume(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700370 }
371 }
372}
373
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700374static jbyteArray
Dianne Hackborn69969e42010-05-04 11:40:40 -0700375onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle)
376{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700377 LOG_TRACE("onSaveInstanceState_native");
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700378
379 jbyteArray array = NULL;
380
Dianne Hackborn69969e42010-05-04 11:40:40 -0700381 if (handle != 0) {
382 NativeCode* code = (NativeCode*)handle;
383 if (code->callbacks.onSaveInstanceState != NULL) {
384 size_t len = 0;
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700385 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
386 if (len > 0) {
387 array = env->NewByteArray(len);
388 if (array != NULL) {
389 env->SetByteArrayRegion(array, 0, len, state);
390 }
391 }
392 if (state != NULL) {
393 free(state);
394 }
Dianne Hackborn69969e42010-05-04 11:40:40 -0700395 }
396 }
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700397
398 return array;
Dianne Hackborn69969e42010-05-04 11:40:40 -0700399}
400
401static void
402onPause_native(JNIEnv* env, jobject clazz, jint handle)
403{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700404 LOG_TRACE("onPause_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700405 if (handle != 0) {
406 NativeCode* code = (NativeCode*)handle;
407 if (code->callbacks.onPause != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700408 code->callbacks.onPause(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700409 }
410 }
411}
412
413static void
414onStop_native(JNIEnv* env, jobject clazz, jint handle)
415{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700416 LOG_TRACE("onStop_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700417 if (handle != 0) {
418 NativeCode* code = (NativeCode*)handle;
419 if (code->callbacks.onStop != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700420 code->callbacks.onStop(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700421 }
422 }
423}
424
425static void
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700426onConfigurationChanged_native(JNIEnv* env, jobject clazz, jint handle)
427{
428 LOG_TRACE("onConfigurationChanged_native");
429 if (handle != 0) {
430 NativeCode* code = (NativeCode*)handle;
431 if (code->callbacks.onConfigurationChanged != NULL) {
432 code->callbacks.onConfigurationChanged(code);
433 }
434 }
435}
436
437static void
Dianne Hackborn69969e42010-05-04 11:40:40 -0700438onLowMemory_native(JNIEnv* env, jobject clazz, jint handle)
439{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700440 LOG_TRACE("onLowMemory_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700441 if (handle != 0) {
442 NativeCode* code = (NativeCode*)handle;
443 if (code->callbacks.onLowMemory != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700444 code->callbacks.onLowMemory(code);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700445 }
446 }
447}
448
449static void
450onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused)
451{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700452 LOG_TRACE("onWindowFocusChanged_native");
Dianne Hackborn69969e42010-05-04 11:40:40 -0700453 if (handle != 0) {
454 NativeCode* code = (NativeCode*)handle;
455 if (code->callbacks.onWindowFocusChanged != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700456 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700457 }
458 }
459}
460
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700461static void
462onSurfaceCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject surface)
463{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700464 LOG_TRACE("onSurfaceCreated_native");
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700465 if (handle != 0) {
466 NativeCode* code = (NativeCode*)handle;
467 code->setSurface(surface);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700468 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700469 code->callbacks.onNativeWindowCreated(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700470 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700471 }
472 }
473}
474
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700475static int32_t getWindowProp(ANativeWindow* window, int what) {
476 int value;
477 int res = window->query(window, what, &value);
478 return res < 0 ? res : value;
479}
480
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700481static void
482onSurfaceChanged_native(JNIEnv* env, jobject clazz, jint handle, jobject surface,
483 jint format, jint width, jint height)
484{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700485 LOG_TRACE("onSurfaceChanged_native");
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700486 if (handle != 0) {
487 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700488 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
489 code->setSurface(surface);
490 if (oldNativeWindow != code->nativeWindow) {
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700491 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700492 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn8ae5a8e2010-07-01 18:44:46 -0700493 oldNativeWindow.get());
494 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700495 if (code->nativeWindow != NULL) {
496 if (code->callbacks.onNativeWindowCreated != NULL) {
497 code->callbacks.onNativeWindowCreated(code,
498 code->nativeWindow.get());
499 }
500 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
501 NATIVE_WINDOW_WIDTH);
502 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
503 NATIVE_WINDOW_HEIGHT);
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700504 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700505 } else {
506 // Maybe it resized?
507 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
508 NATIVE_WINDOW_WIDTH);
509 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
510 NATIVE_WINDOW_HEIGHT);
511 if (newWidth != code->lastWindowWidth
512 || newHeight != code->lastWindowHeight) {
513 if (code->callbacks.onNativeWindowResized != NULL) {
514 code->callbacks.onNativeWindowResized(code,
515 code->nativeWindow.get());
516 }
517 }
518 }
519 }
520}
521
522static void
523onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jint handle)
524{
525 LOG_TRACE("onSurfaceRedrawNeeded_native");
526 if (handle != 0) {
527 NativeCode* code = (NativeCode*)handle;
528 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
529 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700530 }
531 }
532}
533
534static void
535onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surface)
536{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700537 LOG_TRACE("onSurfaceDestroyed_native");
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700538 if (handle != 0) {
539 NativeCode* code = (NativeCode*)handle;
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700540 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
Dianne Hackborn289b9b62010-07-09 11:44:11 -0700541 code->callbacks.onNativeWindowDestroyed(code,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700542 code->nativeWindow.get());
Dianne Hackborn74323fd2010-05-18 17:56:23 -0700543 }
544 code->setSurface(NULL);
545 }
546}
547
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700548static void
Michael Wrighta44dd262013-04-10 21:12:00 -0700549onInputQueueCreated_native(JNIEnv* env, jobject clazz, jint handle, jint queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700550{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700551 LOG_TRACE("onInputChannelCreated_native");
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700552 if (handle != 0) {
553 NativeCode* code = (NativeCode*)handle;
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700554 if (code->callbacks.onInputQueueCreated != NULL) {
Michael Wrighta44dd262013-04-10 21:12:00 -0700555 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
556 code->callbacks.onInputQueueCreated(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700557 }
558 }
559}
560
561static void
Michael Wrighta44dd262013-04-10 21:12:00 -0700562onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jint queuePtr)
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700563{
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700564 LOG_TRACE("onInputChannelDestroyed_native");
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700565 if (handle != 0) {
566 NativeCode* code = (NativeCode*)handle;
Michael Wrighta44dd262013-04-10 21:12:00 -0700567 if (code->callbacks.onInputQueueDestroyed != NULL) {
568 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
569 code->callbacks.onInputQueueDestroyed(code, queue);
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700570 }
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700571 }
572}
573
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700574static void
575onContentRectChanged_native(JNIEnv* env, jobject clazz, jint handle,
576 jint x, jint y, jint w, jint h)
577{
578 LOG_TRACE("onContentRectChanged_native");
579 if (handle != 0) {
580 NativeCode* code = (NativeCode*)handle;
581 if (code->callbacks.onContentRectChanged != NULL) {
582 ARect rect;
583 rect.left = x;
584 rect.top = y;
585 rect.right = x+w;
586 rect.bottom = y+h;
587 code->callbacks.onContentRectChanged(code, &rect);
588 }
589 }
590}
591
Dianne Hackborn69969e42010-05-04 11:40:40 -0700592static const JNINativeMethod g_methods[] = {
Dianne Hackborn805fd7e2011-01-16 18:30:29 -0800593 { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)I",
Dianne Hackborn68267412010-07-02 18:52:01 -0700594 (void*)loadNativeCode_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700595 { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
596 { "onStartNative", "(I)V", (void*)onStart_native },
597 { "onResumeNative", "(I)V", (void*)onResume_native },
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700598 { "onSaveInstanceStateNative", "(I)[B", (void*)onSaveInstanceState_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700599 { "onPauseNative", "(I)V", (void*)onPause_native },
600 { "onStopNative", "(I)V", (void*)onStop_native },
Dianne Hackborn08d5b8f2010-08-04 11:12:40 -0700601 { "onConfigurationChangedNative", "(I)V", (void*)onConfigurationChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700602 { "onLowMemoryNative", "(I)V", (void*)onLowMemory_native },
603 { "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native },
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700604 { "onSurfaceCreatedNative", "(ILandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
605 { "onSurfaceChangedNative", "(ILandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700606 { "onSurfaceRedrawNeededNative", "(ILandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700607 { "onSurfaceDestroyedNative", "(I)V", (void*)onSurfaceDestroyed_native },
Michael Wrighta44dd262013-04-10 21:12:00 -0700608 { "onInputQueueCreatedNative", "(II)V",
609 (void*)onInputQueueCreated_native },
610 { "onInputQueueDestroyedNative", "(II)V",
611 (void*)onInputQueueDestroyed_native },
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700612 { "onContentRectChangedNative", "(IIIII)V", (void*)onContentRectChanged_native },
Dianne Hackborn69969e42010-05-04 11:40:40 -0700613};
614
615static const char* const kNativeActivityPathName = "android/app/NativeActivity";
616
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700617#define FIND_CLASS(var, className) \
618 var = env->FindClass(className); \
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800619 LOG_FATAL_IF(! var, "Unable to find class %s", className);
Dianne Hackborn3c80a4a2010-06-29 19:20:40 -0700620
621#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
622 var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
623 LOG_FATAL_IF(! var, "Unable to find method" methodName);
624
Dianne Hackborn69969e42010-05-04 11:40:40 -0700625int register_android_app_NativeActivity(JNIEnv* env)
626{
Steve Block5baa3a62011-12-20 16:23:08 +0000627 //ALOGD("register_android_app_NativeActivity");
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800628 jclass clazz;
629 FIND_CLASS(clazz, kNativeActivityPathName);
Dianne Hackborn69969e42010-05-04 11:40:40 -0700630
Dianne Hackborndb28a942010-10-21 17:22:30 -0700631 GET_METHOD_ID(gNativeActivityClassInfo.finish,
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800632 clazz,
Dianne Hackborndb28a942010-10-21 17:22:30 -0700633 "finish", "()V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700634 GET_METHOD_ID(gNativeActivityClassInfo.setWindowFlags,
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800635 clazz,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700636 "setWindowFlags", "(II)V");
637 GET_METHOD_ID(gNativeActivityClassInfo.setWindowFormat,
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800638 clazz,
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700639 "setWindowFormat", "(I)V");
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700640 GET_METHOD_ID(gNativeActivityClassInfo.showIme,
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800641 clazz,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700642 "showIme", "(I)V");
643 GET_METHOD_ID(gNativeActivityClassInfo.hideIme,
Carl Shapiro17cc33a2011-03-05 20:53:16 -0800644 clazz,
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700645 "hideIme", "(I)V");
Dianne Hackborn54a181b2010-06-30 18:35:14 -0700646
Dianne Hackborn69969e42010-05-04 11:40:40 -0700647 return AndroidRuntime::registerNativeMethods(
648 env, kNativeActivityPathName,
649 g_methods, NELEM(g_methods));
650}
651
Dianne Hackborna95e4cb2010-06-18 18:09:33 -0700652} // namespace android