1 /*
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
20 #include <poll.h>
21 #include <dlfcn.h>
22 #include <fcntl.h>
23
24 #include <memory>
25
26 #include <android_runtime/android_app_NativeActivity.h>
27 #include <android_runtime/android_util_AssetManager.h>
28 #include <android_runtime/android_view_Surface.h>
29 #include <android_runtime/AndroidRuntime.h>
30 #include <input/InputTransport.h>
31
32 #include <gui/Surface.h>
33
34 #include <system/window.h>
35
36 #include <utils/Looper.h>
37
38 #include "JNIHelp.h"
39 #include "android_os_MessageQueue.h"
40 #include "android_view_InputChannel.h"
41 #include "android_view_KeyEvent.h"
42
43 #include "nativebridge/native_bridge.h"
44 #include "nativeloader/native_loader.h"
45
46 #include "core_jni_helpers.h"
47
48
49 #define LOG_TRACE(...)
50 //#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
51
52 namespace android
53 {
54
55 static const bool kLogTrace = false;
56
57 static struct {
58 jmethodID finish;
59 jmethodID setWindowFlags;
60 jmethodID setWindowFormat;
61 jmethodID showIme;
62 jmethodID hideIme;
63 } gNativeActivityClassInfo;
64
65 // ------------------------------------------------------------------------
66
67 struct ActivityWork {
68 int32_t cmd;
69 int32_t arg1;
70 int32_t arg2;
71 };
72
73 enum {
74 CMD_FINISH = 1,
75 CMD_SET_WINDOW_FORMAT,
76 CMD_SET_WINDOW_FLAGS,
77 CMD_SHOW_SOFT_INPUT,
78 CMD_HIDE_SOFT_INPUT,
79 };
80
write_work(int fd,int32_t cmd,int32_t arg1=0,int32_t arg2=0)81 static 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;
86
87 if (kLogTrace) {
88 ALOGD("write_work: cmd=%d", cmd);
89 }
90
91 restart:
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
99 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
100 else ALOGW("Truncated writing to work fd: %d", res);
101 }
102
read_work(int fd,ActivityWork * outWork)103 static 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
108 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
109 else ALOGW("Truncated reading work fd: %d", res);
110 return false;
111 }
112
113 /*
114 * Native state for interacting with the NativeActivity class.
115 */
116 struct NativeCode : public ANativeActivity {
NativeCodeandroid::NativeCode117 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
118 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
119 memset(&callbacks, 0, sizeof(callbacks));
120 dlhandle = _dlhandle;
121 createActivityFunc = _createFunc;
122 nativeWindow = NULL;
123 mainWorkRead = mainWorkWrite = -1;
124 }
125
~NativeCodeandroid::NativeCode126 ~NativeCode() {
127 if (callbacks.onDestroy != NULL) {
128 callbacks.onDestroy(this);
129 }
130 if (env != NULL && clazz != NULL) {
131 env->DeleteGlobalRef(clazz);
132 }
133 if (messageQueue != NULL && mainWorkRead >= 0) {
134 messageQueue->getLooper()->removeFd(mainWorkRead);
135 }
136 setSurface(NULL);
137 if (mainWorkRead >= 0) close(mainWorkRead);
138 if (mainWorkWrite >= 0) close(mainWorkWrite);
139 if (dlhandle != NULL) {
140 // 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);
144 }
145 }
146
setSurfaceandroid::NativeCode147 void setSurface(jobject _surface) {
148 if (_surface != NULL) {
149 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
150 } else {
151 nativeWindow = NULL;
152 }
153 }
154
155 ANativeActivityCallbacks callbacks;
156
157 void* dlhandle;
158 ANativeActivity_createFunc* createActivityFunc;
159
160 String8 internalDataPathObj;
161 String8 externalDataPathObj;
162 String8 obbPathObj;
163
164 sp<ANativeWindow> nativeWindow;
165 int32_t lastWindowWidth;
166 int32_t lastWindowHeight;
167
168 // These are used to wake up the main thread to process work.
169 int mainWorkRead;
170 int mainWorkWrite;
171 sp<MessageQueue> messageQueue;
172 };
173
android_NativeActivity_finish(ANativeActivity * activity)174 void android_NativeActivity_finish(ANativeActivity* activity) {
175 NativeCode* code = static_cast<NativeCode*>(activity);
176 write_work(code->mainWorkWrite, CMD_FINISH, 0);
177 }
178
android_NativeActivity_setWindowFormat(ANativeActivity * activity,int32_t format)179 void 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
android_NativeActivity_setWindowFlags(ANativeActivity * activity,int32_t values,int32_t mask)185 void 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
android_NativeActivity_showSoftInput(ANativeActivity * activity,int32_t flags)191 void 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
android_NativeActivity_hideSoftInput(ANativeActivity * activity,int32_t flags)197 void 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
203 // ------------------------------------------------------------------------
204
205 /*
206 * Callback for handling native events on the application's main thread.
207 */
mainWorkCallback(int fd,int events,void * data)208 static int mainWorkCallback(int fd, int events, void* data) {
209 NativeCode* code = (NativeCode*)data;
210 if ((events & POLLIN) == 0) {
211 return 1;
212 }
213
214 ActivityWork work;
215 if (!read_work(code->mainWorkRead, &work)) {
216 return 1;
217 }
218
219 if (kLogTrace) {
220 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
221 }
222
223 switch (work.cmd) {
224 case CMD_FINISH: {
225 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
226 code->messageQueue->raiseAndClearException(code->env, "finish");
227 } break;
228 case CMD_SET_WINDOW_FORMAT: {
229 code->env->CallVoidMethod(code->clazz,
230 gNativeActivityClassInfo.setWindowFormat, work.arg1);
231 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
232 } break;
233 case CMD_SET_WINDOW_FLAGS: {
234 code->env->CallVoidMethod(code->clazz,
235 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
236 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
237 } break;
238 case CMD_SHOW_SOFT_INPUT: {
239 code->env->CallVoidMethod(code->clazz,
240 gNativeActivityClassInfo.showIme, work.arg1);
241 code->messageQueue->raiseAndClearException(code->env, "showIme");
242 } break;
243 case CMD_HIDE_SOFT_INPUT: {
244 code->env->CallVoidMethod(code->clazz,
245 gNativeActivityClassInfo.hideIme, work.arg1);
246 code->messageQueue->raiseAndClearException(code->env, "hideIme");
247 } break;
248 default:
249 ALOGW("Unknown work command: %d", work.cmd);
250 break;
251 }
252
253 return 1;
254 }
255
256 // ------------------------------------------------------------------------
257
258 static jlong
loadNativeCode_native(JNIEnv * env,jobject clazz,jstring path,jstring funcName,jobject messageQueue,jstring internalDataDir,jstring obbDir,jstring externalDataDir,jint sdkVersion,jobject jAssetMgr,jbyteArray savedState,jobject classLoader,jstring libraryPath)259 loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
260 jobject messageQueue, jstring internalDataDir, jstring obbDir,
261 jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
262 jbyteArray savedState, jobject classLoader, jstring libraryPath) {
263 if (kLogTrace) {
264 ALOGD("loadNativeCode_native");
265 }
266
267 const char* pathStr = env->GetStringUTFChars(path, NULL);
268 std::unique_ptr<NativeCode> code;
269 bool needNativeBridge = false;
270
271 void* handle = OpenNativeLibrary(env, sdkVersion, pathStr, classLoader, libraryPath);
272 if (handle == NULL) {
273 if (NativeBridgeIsSupported(pathStr)) {
274 handle = NativeBridgeLoadLibrary(pathStr, RTLD_LAZY);
275 needNativeBridge = true;
276 }
277 }
278 env->ReleaseStringUTFChars(path, pathStr);
279
280 if (handle != NULL) {
281 void* funcPtr = NULL;
282 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
283 if (needNativeBridge) {
284 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
285 } else {
286 funcPtr = dlsym(handle, funcStr);
287 }
288
289 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
290 env->ReleaseStringUTFChars(funcName, funcStr);
291
292 if (code->createActivityFunc == NULL) {
293 ALOGW("ANativeActivity_onCreate not found");
294 return 0;
295 }
296
297 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
298 if (code->messageQueue == NULL) {
299 ALOGW("Unable to retrieve native MessageQueue");
300 return 0;
301 }
302
303 int msgpipe[2];
304 if (pipe(msgpipe)) {
305 ALOGW("could not create pipe: %s", strerror(errno));
306 return 0;
307 }
308 code->mainWorkRead = msgpipe[0];
309 code->mainWorkWrite = msgpipe[1];
310 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));
316 code->messageQueue->getLooper()->addFd(
317 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
318
319 code->ANativeActivity::callbacks = &code->callbacks;
320 if (env->GetJavaVM(&code->vm) < 0) {
321 ALOGW("NativeActivity GetJavaVM failed");
322 return 0;
323 }
324 code->env = env;
325 code->clazz = env->NewGlobalRef(clazz);
326
327 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
328 code->internalDataPathObj = dirStr;
329 code->internalDataPath = code->internalDataPathObj.string();
330 env->ReleaseStringUTFChars(internalDataDir, dirStr);
331
332 if (externalDataDir != NULL) {
333 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
334 code->externalDataPathObj = dirStr;
335 env->ReleaseStringUTFChars(externalDataDir, dirStr);
336 }
337 code->externalDataPath = code->externalDataPathObj.string();
338
339 code->sdkVersion = sdkVersion;
340
341 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
342
343 if (obbDir != NULL) {
344 dirStr = env->GetStringUTFChars(obbDir, NULL);
345 code->obbPathObj = dirStr;
346 env->ReleaseStringUTFChars(obbDir, dirStr);
347 }
348 code->obbPath = code->obbPathObj.string();
349
350 jbyte* rawSavedState = NULL;
351 jsize rawSavedSize = 0;
352 if (savedState != NULL) {
353 rawSavedState = env->GetByteArrayElements(savedState, NULL);
354 rawSavedSize = env->GetArrayLength(savedState);
355 }
356
357 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
358
359 if (rawSavedState != NULL) {
360 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
361 }
362 }
363
364 return (jlong)code.release();
365 }
366
getDlError_native(JNIEnv * env,jobject clazz)367 static jstring getDlError_native(JNIEnv* env, jobject clazz) {
368 return env->NewStringUTF(dlerror());
369 }
370
371 static void
unloadNativeCode_native(JNIEnv * env,jobject clazz,jlong handle)372 unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
373 {
374 if (kLogTrace) {
375 ALOGD("unloadNativeCode_native");
376 }
377 if (handle != 0) {
378 NativeCode* code = (NativeCode*)handle;
379 delete code;
380 }
381 }
382
383 static void
onStart_native(JNIEnv * env,jobject clazz,jlong handle)384 onStart_native(JNIEnv* env, jobject clazz, jlong handle)
385 {
386 if (kLogTrace) {
387 ALOGD("onStart_native");
388 }
389 if (handle != 0) {
390 NativeCode* code = (NativeCode*)handle;
391 if (code->callbacks.onStart != NULL) {
392 code->callbacks.onStart(code);
393 }
394 }
395 }
396
397 static void
onResume_native(JNIEnv * env,jobject clazz,jlong handle)398 onResume_native(JNIEnv* env, jobject clazz, jlong handle)
399 {
400 if (kLogTrace) {
401 ALOGD("onResume_native");
402 }
403 if (handle != 0) {
404 NativeCode* code = (NativeCode*)handle;
405 if (code->callbacks.onResume != NULL) {
406 code->callbacks.onResume(code);
407 }
408 }
409 }
410
411 static jbyteArray
onSaveInstanceState_native(JNIEnv * env,jobject clazz,jlong handle)412 onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
413 {
414 if (kLogTrace) {
415 ALOGD("onSaveInstanceState_native");
416 }
417
418 jbyteArray array = NULL;
419
420 if (handle != 0) {
421 NativeCode* code = (NativeCode*)handle;
422 if (code->callbacks.onSaveInstanceState != NULL) {
423 size_t len = 0;
424 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 }
434 }
435 }
436
437 return array;
438 }
439
440 static void
onPause_native(JNIEnv * env,jobject clazz,jlong handle)441 onPause_native(JNIEnv* env, jobject clazz, jlong handle)
442 {
443 if (kLogTrace) {
444 ALOGD("onPause_native");
445 }
446 if (handle != 0) {
447 NativeCode* code = (NativeCode*)handle;
448 if (code->callbacks.onPause != NULL) {
449 code->callbacks.onPause(code);
450 }
451 }
452 }
453
454 static void
onStop_native(JNIEnv * env,jobject clazz,jlong handle)455 onStop_native(JNIEnv* env, jobject clazz, jlong handle)
456 {
457 if (kLogTrace) {
458 ALOGD("onStop_native");
459 }
460 if (handle != 0) {
461 NativeCode* code = (NativeCode*)handle;
462 if (code->callbacks.onStop != NULL) {
463 code->callbacks.onStop(code);
464 }
465 }
466 }
467
468 static void
onConfigurationChanged_native(JNIEnv * env,jobject clazz,jlong handle)469 onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
470 {
471 if (kLogTrace) {
472 ALOGD("onConfigurationChanged_native");
473 }
474 if (handle != 0) {
475 NativeCode* code = (NativeCode*)handle;
476 if (code->callbacks.onConfigurationChanged != NULL) {
477 code->callbacks.onConfigurationChanged(code);
478 }
479 }
480 }
481
482 static void
onLowMemory_native(JNIEnv * env,jobject clazz,jlong handle)483 onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
484 {
485 if (kLogTrace) {
486 ALOGD("onLowMemory_native");
487 }
488 if (handle != 0) {
489 NativeCode* code = (NativeCode*)handle;
490 if (code->callbacks.onLowMemory != NULL) {
491 code->callbacks.onLowMemory(code);
492 }
493 }
494 }
495
496 static void
onWindowFocusChanged_native(JNIEnv * env,jobject clazz,jlong handle,jboolean focused)497 onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
498 {
499 if (kLogTrace) {
500 ALOGD("onWindowFocusChanged_native");
501 }
502 if (handle != 0) {
503 NativeCode* code = (NativeCode*)handle;
504 if (code->callbacks.onWindowFocusChanged != NULL) {
505 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
506 }
507 }
508 }
509
510 static void
onSurfaceCreated_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface)511 onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
512 {
513 if (kLogTrace) {
514 ALOGD("onSurfaceCreated_native");
515 }
516 if (handle != 0) {
517 NativeCode* code = (NativeCode*)handle;
518 code->setSurface(surface);
519 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
520 code->callbacks.onNativeWindowCreated(code,
521 code->nativeWindow.get());
522 }
523 }
524 }
525
getWindowProp(ANativeWindow * window,int what)526 static 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
532 static void
onSurfaceChanged_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface,jint format,jint width,jint height)533 onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
534 jint format, jint width, jint height)
535 {
536 if (kLogTrace) {
537 ALOGD("onSurfaceChanged_native");
538 }
539 if (handle != 0) {
540 NativeCode* code = (NativeCode*)handle;
541 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
542 code->setSurface(surface);
543 if (oldNativeWindow != code->nativeWindow) {
544 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
545 code->callbacks.onNativeWindowDestroyed(code,
546 oldNativeWindow.get());
547 }
548 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);
557 }
558 } 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
575 static void
onSurfaceRedrawNeeded_native(JNIEnv * env,jobject clazz,jlong handle)576 onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
577 {
578 if (kLogTrace) {
579 ALOGD("onSurfaceRedrawNeeded_native");
580 }
581 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());
585 }
586 }
587 }
588
589 static void
onSurfaceDestroyed_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface)590 onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
591 {
592 if (kLogTrace) {
593 ALOGD("onSurfaceDestroyed_native");
594 }
595 if (handle != 0) {
596 NativeCode* code = (NativeCode*)handle;
597 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
598 code->callbacks.onNativeWindowDestroyed(code,
599 code->nativeWindow.get());
600 }
601 code->setSurface(NULL);
602 }
603 }
604
605 static void
onInputQueueCreated_native(JNIEnv * env,jobject clazz,jlong handle,jlong queuePtr)606 onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
607 {
608 if (kLogTrace) {
609 ALOGD("onInputChannelCreated_native");
610 }
611 if (handle != 0) {
612 NativeCode* code = (NativeCode*)handle;
613 if (code->callbacks.onInputQueueCreated != NULL) {
614 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
615 code->callbacks.onInputQueueCreated(code, queue);
616 }
617 }
618 }
619
620 static void
onInputQueueDestroyed_native(JNIEnv * env,jobject clazz,jlong handle,jlong queuePtr)621 onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
622 {
623 if (kLogTrace) {
624 ALOGD("onInputChannelDestroyed_native");
625 }
626 if (handle != 0) {
627 NativeCode* code = (NativeCode*)handle;
628 if (code->callbacks.onInputQueueDestroyed != NULL) {
629 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
630 code->callbacks.onInputQueueDestroyed(code, queue);
631 }
632 }
633 }
634
635 static void
onContentRectChanged_native(JNIEnv * env,jobject clazz,jlong handle,jint x,jint y,jint w,jint h)636 onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
637 jint x, jint y, jint w, jint h)
638 {
639 if (kLogTrace) {
640 ALOGD("onContentRectChanged_native");
641 }
642 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
655 static const JNINativeMethod g_methods[] = {
656 { "loadNativeCode",
657 "(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",
658 (void*)loadNativeCode_native },
659 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
660 { "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",
674 (void*)onInputQueueCreated_native },
675 { "onInputQueueDestroyedNative", "(JJ)V",
676 (void*)onInputQueueDestroyed_native },
677 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
678 };
679
680 static const char* const kNativeActivityPathName = "android/app/NativeActivity";
681
register_android_app_NativeActivity(JNIEnv * env)682 int register_android_app_NativeActivity(JNIEnv* env)
683 {
684 //ALOGD("register_android_app_NativeActivity");
685 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
686
687 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");
694
695 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
696 }
697
698 } // namespace android
699