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 <nativehelper/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 #include <nativehelper/ScopedUtfChars.h>
49
50 #define LOG_TRACE(...)
51 //#define LOG_TRACE(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
52
53 namespace android
54 {
55
56 static const bool kLogTrace = false;
57
58 static struct {
59 jmethodID finish;
60 jmethodID setWindowFlags;
61 jmethodID setWindowFormat;
62 jmethodID showIme;
63 jmethodID hideIme;
64 } gNativeActivityClassInfo;
65
66 // ------------------------------------------------------------------------
67
68 struct ActivityWork {
69 int32_t cmd;
70 int32_t arg1;
71 int32_t arg2;
72 };
73
74 enum {
75 CMD_FINISH = 1,
76 CMD_SET_WINDOW_FORMAT,
77 CMD_SET_WINDOW_FLAGS,
78 CMD_SHOW_SOFT_INPUT,
79 CMD_HIDE_SOFT_INPUT,
80 };
81
write_work(int fd,int32_t cmd,int32_t arg1=0,int32_t arg2=0)82 static void write_work(int fd, int32_t cmd, int32_t arg1=0, int32_t arg2=0) {
83 ActivityWork work;
84 work.cmd = cmd;
85 work.arg1 = arg1;
86 work.arg2 = arg2;
87
88 if (kLogTrace) {
89 ALOGD("write_work: cmd=%d", cmd);
90 }
91
92 restart:
93 int res = write(fd, &work, sizeof(work));
94 if (res < 0 && errno == EINTR) {
95 goto restart;
96 }
97
98 if (res == sizeof(work)) return;
99
100 if (res < 0) ALOGW("Failed writing to work fd: %s", strerror(errno));
101 else ALOGW("Truncated writing to work fd: %d", res);
102 }
103
read_work(int fd,ActivityWork * outWork)104 static bool read_work(int fd, ActivityWork* outWork) {
105 int res = read(fd, outWork, sizeof(ActivityWork));
106 // no need to worry about EINTR, poll loop will just come back again.
107 if (res == sizeof(ActivityWork)) return true;
108
109 if (res < 0) ALOGW("Failed reading work fd: %s", strerror(errno));
110 else ALOGW("Truncated reading work fd: %d", res);
111 return false;
112 }
113
114 /*
115 * Native state for interacting with the NativeActivity class.
116 */
117 struct NativeCode : public ANativeActivity {
NativeCodeandroid::NativeCode118 NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
119 memset((ANativeActivity*)this, 0, sizeof(ANativeActivity));
120 memset(&callbacks, 0, sizeof(callbacks));
121 dlhandle = _dlhandle;
122 createActivityFunc = _createFunc;
123 nativeWindow = NULL;
124 mainWorkRead = mainWorkWrite = -1;
125 }
126
~NativeCodeandroid::NativeCode127 ~NativeCode() {
128 if (callbacks.onDestroy != NULL) {
129 callbacks.onDestroy(this);
130 }
131 if (env != NULL) {
132 if (clazz != NULL) {
133 env->DeleteGlobalRef(clazz);
134 }
135 if (javaAssetManager != NULL) {
136 env->DeleteGlobalRef(javaAssetManager);
137 }
138 }
139 if (messageQueue != NULL && mainWorkRead >= 0) {
140 messageQueue->getLooper()->removeFd(mainWorkRead);
141 }
142 setSurface(NULL);
143 if (mainWorkRead >= 0) close(mainWorkRead);
144 if (mainWorkWrite >= 0) close(mainWorkWrite);
145 if (dlhandle != NULL) {
146 // for now don't unload... we probably should clean this
147 // up and only keep one open dlhandle per proc, since there
148 // is really no benefit to unloading the code.
149 //dlclose(dlhandle);
150 }
151 }
152
setSurfaceandroid::NativeCode153 void setSurface(jobject _surface) {
154 if (_surface != NULL) {
155 nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
156 } else {
157 nativeWindow = NULL;
158 }
159 }
160
161 ANativeActivityCallbacks callbacks;
162
163 void* dlhandle;
164 ANativeActivity_createFunc* createActivityFunc;
165
166 String8 internalDataPathObj;
167 String8 externalDataPathObj;
168 String8 obbPathObj;
169
170 sp<ANativeWindow> nativeWindow;
171 int32_t lastWindowWidth;
172 int32_t lastWindowHeight;
173
174 // These are used to wake up the main thread to process work.
175 int mainWorkRead;
176 int mainWorkWrite;
177 sp<MessageQueue> messageQueue;
178
179 // Need to hold on to a reference here in case the upper layers destroy our
180 // AssetManager.
181 jobject javaAssetManager;
182 };
183
android_NativeActivity_finish(ANativeActivity * activity)184 void android_NativeActivity_finish(ANativeActivity* activity) {
185 NativeCode* code = static_cast<NativeCode*>(activity);
186 write_work(code->mainWorkWrite, CMD_FINISH, 0);
187 }
188
android_NativeActivity_setWindowFormat(ANativeActivity * activity,int32_t format)189 void android_NativeActivity_setWindowFormat(
190 ANativeActivity* activity, int32_t format) {
191 NativeCode* code = static_cast<NativeCode*>(activity);
192 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FORMAT, format);
193 }
194
android_NativeActivity_setWindowFlags(ANativeActivity * activity,int32_t values,int32_t mask)195 void android_NativeActivity_setWindowFlags(
196 ANativeActivity* activity, int32_t values, int32_t mask) {
197 NativeCode* code = static_cast<NativeCode*>(activity);
198 write_work(code->mainWorkWrite, CMD_SET_WINDOW_FLAGS, values, mask);
199 }
200
android_NativeActivity_showSoftInput(ANativeActivity * activity,int32_t flags)201 void android_NativeActivity_showSoftInput(
202 ANativeActivity* activity, int32_t flags) {
203 NativeCode* code = static_cast<NativeCode*>(activity);
204 write_work(code->mainWorkWrite, CMD_SHOW_SOFT_INPUT, flags);
205 }
206
android_NativeActivity_hideSoftInput(ANativeActivity * activity,int32_t flags)207 void android_NativeActivity_hideSoftInput(
208 ANativeActivity* activity, int32_t flags) {
209 NativeCode* code = static_cast<NativeCode*>(activity);
210 write_work(code->mainWorkWrite, CMD_HIDE_SOFT_INPUT, flags);
211 }
212
213 // ------------------------------------------------------------------------
214
215 /*
216 * Callback for handling native events on the application's main thread.
217 */
mainWorkCallback(int fd,int events,void * data)218 static int mainWorkCallback(int fd, int events, void* data) {
219 NativeCode* code = (NativeCode*)data;
220 if ((events & POLLIN) == 0) {
221 return 1;
222 }
223
224 ActivityWork work;
225 if (!read_work(code->mainWorkRead, &work)) {
226 return 1;
227 }
228
229 if (kLogTrace) {
230 ALOGD("mainWorkCallback: cmd=%d", work.cmd);
231 }
232
233 switch (work.cmd) {
234 case CMD_FINISH: {
235 code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
236 code->messageQueue->raiseAndClearException(code->env, "finish");
237 } break;
238 case CMD_SET_WINDOW_FORMAT: {
239 code->env->CallVoidMethod(code->clazz,
240 gNativeActivityClassInfo.setWindowFormat, work.arg1);
241 code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
242 } break;
243 case CMD_SET_WINDOW_FLAGS: {
244 code->env->CallVoidMethod(code->clazz,
245 gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
246 code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
247 } break;
248 case CMD_SHOW_SOFT_INPUT: {
249 code->env->CallVoidMethod(code->clazz,
250 gNativeActivityClassInfo.showIme, work.arg1);
251 code->messageQueue->raiseAndClearException(code->env, "showIme");
252 } break;
253 case CMD_HIDE_SOFT_INPUT: {
254 code->env->CallVoidMethod(code->clazz,
255 gNativeActivityClassInfo.hideIme, work.arg1);
256 code->messageQueue->raiseAndClearException(code->env, "hideIme");
257 } break;
258 default:
259 ALOGW("Unknown work command: %d", work.cmd);
260 break;
261 }
262
263 return 1;
264 }
265
266 // ------------------------------------------------------------------------
267
268 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)269 loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
270 jobject messageQueue, jstring internalDataDir, jstring obbDir,
271 jstring externalDataDir, jint sdkVersion, jobject jAssetMgr,
272 jbyteArray savedState, jobject classLoader, jstring libraryPath) {
273 if (kLogTrace) {
274 ALOGD("loadNativeCode_native");
275 }
276
277 ScopedUtfChars pathStr(env, path);
278 std::unique_ptr<NativeCode> code;
279 bool needs_native_bridge = false;
280 std::string error_msg;
281
282 void* handle = OpenNativeLibrary(env,
283 sdkVersion,
284 pathStr.c_str(),
285 classLoader,
286 libraryPath,
287 &needs_native_bridge,
288 &error_msg);
289
290 if (handle == nullptr) {
291 ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s",
292 pathStr.c_str(),
293 error_msg.c_str());
294 return 0;
295 }
296
297 void* funcPtr = NULL;
298 const char* funcStr = env->GetStringUTFChars(funcName, NULL);
299 if (needs_native_bridge) {
300 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0);
301 } else {
302 funcPtr = dlsym(handle, funcStr);
303 }
304
305 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr));
306 env->ReleaseStringUTFChars(funcName, funcStr);
307
308 if (code->createActivityFunc == NULL) {
309 ALOGW("ANativeActivity_onCreate not found");
310 return 0;
311 }
312
313 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
314 if (code->messageQueue == NULL) {
315 ALOGW("Unable to retrieve native MessageQueue");
316 return 0;
317 }
318
319 int msgpipe[2];
320 if (pipe(msgpipe)) {
321 ALOGW("could not create pipe: %s", strerror(errno));
322 return 0;
323 }
324 code->mainWorkRead = msgpipe[0];
325 code->mainWorkWrite = msgpipe[1];
326 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK);
327 SLOGW_IF(result != 0, "Could not make main work read pipe "
328 "non-blocking: %s", strerror(errno));
329 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
330 SLOGW_IF(result != 0, "Could not make main work write pipe "
331 "non-blocking: %s", strerror(errno));
332 code->messageQueue->getLooper()->addFd(
333 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get());
334
335 code->ANativeActivity::callbacks = &code->callbacks;
336 if (env->GetJavaVM(&code->vm) < 0) {
337 ALOGW("NativeActivity GetJavaVM failed");
338 return 0;
339 }
340 code->env = env;
341 code->clazz = env->NewGlobalRef(clazz);
342
343 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
344 code->internalDataPathObj = dirStr;
345 code->internalDataPath = code->internalDataPathObj.string();
346 env->ReleaseStringUTFChars(internalDataDir, dirStr);
347
348 if (externalDataDir != NULL) {
349 dirStr = env->GetStringUTFChars(externalDataDir, NULL);
350 code->externalDataPathObj = dirStr;
351 env->ReleaseStringUTFChars(externalDataDir, dirStr);
352 }
353 code->externalDataPath = code->externalDataPathObj.string();
354
355 code->sdkVersion = sdkVersion;
356
357 code->javaAssetManager = env->NewGlobalRef(jAssetMgr);
358 code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
359
360 if (obbDir != NULL) {
361 dirStr = env->GetStringUTFChars(obbDir, NULL);
362 code->obbPathObj = dirStr;
363 env->ReleaseStringUTFChars(obbDir, dirStr);
364 }
365 code->obbPath = code->obbPathObj.string();
366
367 jbyte* rawSavedState = NULL;
368 jsize rawSavedSize = 0;
369 if (savedState != NULL) {
370 rawSavedState = env->GetByteArrayElements(savedState, NULL);
371 rawSavedSize = env->GetArrayLength(savedState);
372 }
373
374 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize);
375
376 if (rawSavedState != NULL) {
377 env->ReleaseByteArrayElements(savedState, rawSavedState, 0);
378 }
379
380 return (jlong)code.release();
381 }
382
getDlError_native(JNIEnv * env,jobject clazz)383 static jstring getDlError_native(JNIEnv* env, jobject clazz) {
384 return env->NewStringUTF(dlerror());
385 }
386
387 static void
unloadNativeCode_native(JNIEnv * env,jobject clazz,jlong handle)388 unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle)
389 {
390 if (kLogTrace) {
391 ALOGD("unloadNativeCode_native");
392 }
393 if (handle != 0) {
394 NativeCode* code = (NativeCode*)handle;
395 delete code;
396 }
397 }
398
399 static void
onStart_native(JNIEnv * env,jobject clazz,jlong handle)400 onStart_native(JNIEnv* env, jobject clazz, jlong handle)
401 {
402 if (kLogTrace) {
403 ALOGD("onStart_native");
404 }
405 if (handle != 0) {
406 NativeCode* code = (NativeCode*)handle;
407 if (code->callbacks.onStart != NULL) {
408 code->callbacks.onStart(code);
409 }
410 }
411 }
412
413 static void
onResume_native(JNIEnv * env,jobject clazz,jlong handle)414 onResume_native(JNIEnv* env, jobject clazz, jlong handle)
415 {
416 if (kLogTrace) {
417 ALOGD("onResume_native");
418 }
419 if (handle != 0) {
420 NativeCode* code = (NativeCode*)handle;
421 if (code->callbacks.onResume != NULL) {
422 code->callbacks.onResume(code);
423 }
424 }
425 }
426
427 static jbyteArray
onSaveInstanceState_native(JNIEnv * env,jobject clazz,jlong handle)428 onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle)
429 {
430 if (kLogTrace) {
431 ALOGD("onSaveInstanceState_native");
432 }
433
434 jbyteArray array = NULL;
435
436 if (handle != 0) {
437 NativeCode* code = (NativeCode*)handle;
438 if (code->callbacks.onSaveInstanceState != NULL) {
439 size_t len = 0;
440 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len);
441 if (len > 0) {
442 array = env->NewByteArray(len);
443 if (array != NULL) {
444 env->SetByteArrayRegion(array, 0, len, state);
445 }
446 }
447 if (state != NULL) {
448 free(state);
449 }
450 }
451 }
452
453 return array;
454 }
455
456 static void
onPause_native(JNIEnv * env,jobject clazz,jlong handle)457 onPause_native(JNIEnv* env, jobject clazz, jlong handle)
458 {
459 if (kLogTrace) {
460 ALOGD("onPause_native");
461 }
462 if (handle != 0) {
463 NativeCode* code = (NativeCode*)handle;
464 if (code->callbacks.onPause != NULL) {
465 code->callbacks.onPause(code);
466 }
467 }
468 }
469
470 static void
onStop_native(JNIEnv * env,jobject clazz,jlong handle)471 onStop_native(JNIEnv* env, jobject clazz, jlong handle)
472 {
473 if (kLogTrace) {
474 ALOGD("onStop_native");
475 }
476 if (handle != 0) {
477 NativeCode* code = (NativeCode*)handle;
478 if (code->callbacks.onStop != NULL) {
479 code->callbacks.onStop(code);
480 }
481 }
482 }
483
484 static void
onConfigurationChanged_native(JNIEnv * env,jobject clazz,jlong handle)485 onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle)
486 {
487 if (kLogTrace) {
488 ALOGD("onConfigurationChanged_native");
489 }
490 if (handle != 0) {
491 NativeCode* code = (NativeCode*)handle;
492 if (code->callbacks.onConfigurationChanged != NULL) {
493 code->callbacks.onConfigurationChanged(code);
494 }
495 }
496 }
497
498 static void
onLowMemory_native(JNIEnv * env,jobject clazz,jlong handle)499 onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle)
500 {
501 if (kLogTrace) {
502 ALOGD("onLowMemory_native");
503 }
504 if (handle != 0) {
505 NativeCode* code = (NativeCode*)handle;
506 if (code->callbacks.onLowMemory != NULL) {
507 code->callbacks.onLowMemory(code);
508 }
509 }
510 }
511
512 static void
onWindowFocusChanged_native(JNIEnv * env,jobject clazz,jlong handle,jboolean focused)513 onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused)
514 {
515 if (kLogTrace) {
516 ALOGD("onWindowFocusChanged_native");
517 }
518 if (handle != 0) {
519 NativeCode* code = (NativeCode*)handle;
520 if (code->callbacks.onWindowFocusChanged != NULL) {
521 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0);
522 }
523 }
524 }
525
526 static void
onSurfaceCreated_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface)527 onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
528 {
529 if (kLogTrace) {
530 ALOGD("onSurfaceCreated_native");
531 }
532 if (handle != 0) {
533 NativeCode* code = (NativeCode*)handle;
534 code->setSurface(surface);
535 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
536 code->callbacks.onNativeWindowCreated(code,
537 code->nativeWindow.get());
538 }
539 }
540 }
541
getWindowProp(ANativeWindow * window,int what)542 static int32_t getWindowProp(ANativeWindow* window, int what) {
543 int value;
544 int res = window->query(window, what, &value);
545 return res < 0 ? res : value;
546 }
547
548 static void
onSurfaceChanged_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface,jint format,jint width,jint height)549 onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface,
550 jint format, jint width, jint height)
551 {
552 if (kLogTrace) {
553 ALOGD("onSurfaceChanged_native");
554 }
555 if (handle != 0) {
556 NativeCode* code = (NativeCode*)handle;
557 sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
558 code->setSurface(surface);
559 if (oldNativeWindow != code->nativeWindow) {
560 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
561 code->callbacks.onNativeWindowDestroyed(code,
562 oldNativeWindow.get());
563 }
564 if (code->nativeWindow != NULL) {
565 if (code->callbacks.onNativeWindowCreated != NULL) {
566 code->callbacks.onNativeWindowCreated(code,
567 code->nativeWindow.get());
568 }
569 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(),
570 NATIVE_WINDOW_WIDTH);
571 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(),
572 NATIVE_WINDOW_HEIGHT);
573 }
574 } else {
575 // Maybe it resized?
576 int32_t newWidth = getWindowProp(code->nativeWindow.get(),
577 NATIVE_WINDOW_WIDTH);
578 int32_t newHeight = getWindowProp(code->nativeWindow.get(),
579 NATIVE_WINDOW_HEIGHT);
580 if (newWidth != code->lastWindowWidth
581 || newHeight != code->lastWindowHeight) {
582 if (code->callbacks.onNativeWindowResized != NULL) {
583 code->callbacks.onNativeWindowResized(code,
584 code->nativeWindow.get());
585 }
586 }
587 }
588 }
589 }
590
591 static void
onSurfaceRedrawNeeded_native(JNIEnv * env,jobject clazz,jlong handle)592 onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle)
593 {
594 if (kLogTrace) {
595 ALOGD("onSurfaceRedrawNeeded_native");
596 }
597 if (handle != 0) {
598 NativeCode* code = (NativeCode*)handle;
599 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) {
600 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get());
601 }
602 }
603 }
604
605 static void
onSurfaceDestroyed_native(JNIEnv * env,jobject clazz,jlong handle,jobject surface)606 onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface)
607 {
608 if (kLogTrace) {
609 ALOGD("onSurfaceDestroyed_native");
610 }
611 if (handle != 0) {
612 NativeCode* code = (NativeCode*)handle;
613 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
614 code->callbacks.onNativeWindowDestroyed(code,
615 code->nativeWindow.get());
616 }
617 code->setSurface(NULL);
618 }
619 }
620
621 static void
onInputQueueCreated_native(JNIEnv * env,jobject clazz,jlong handle,jlong queuePtr)622 onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
623 {
624 if (kLogTrace) {
625 ALOGD("onInputChannelCreated_native");
626 }
627 if (handle != 0) {
628 NativeCode* code = (NativeCode*)handle;
629 if (code->callbacks.onInputQueueCreated != NULL) {
630 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
631 code->callbacks.onInputQueueCreated(code, queue);
632 }
633 }
634 }
635
636 static void
onInputQueueDestroyed_native(JNIEnv * env,jobject clazz,jlong handle,jlong queuePtr)637 onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr)
638 {
639 if (kLogTrace) {
640 ALOGD("onInputChannelDestroyed_native");
641 }
642 if (handle != 0) {
643 NativeCode* code = (NativeCode*)handle;
644 if (code->callbacks.onInputQueueDestroyed != NULL) {
645 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr);
646 code->callbacks.onInputQueueDestroyed(code, queue);
647 }
648 }
649 }
650
651 static void
onContentRectChanged_native(JNIEnv * env,jobject clazz,jlong handle,jint x,jint y,jint w,jint h)652 onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle,
653 jint x, jint y, jint w, jint h)
654 {
655 if (kLogTrace) {
656 ALOGD("onContentRectChanged_native");
657 }
658 if (handle != 0) {
659 NativeCode* code = (NativeCode*)handle;
660 if (code->callbacks.onContentRectChanged != NULL) {
661 ARect rect;
662 rect.left = x;
663 rect.top = y;
664 rect.right = x+w;
665 rect.bottom = y+h;
666 code->callbacks.onContentRectChanged(code, &rect);
667 }
668 }
669 }
670
671 static const JNINativeMethod g_methods[] = {
672 { "loadNativeCode",
673 "(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",
674 (void*)loadNativeCode_native },
675 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native },
676 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native },
677 { "onStartNative", "(J)V", (void*)onStart_native },
678 { "onResumeNative", "(J)V", (void*)onResume_native },
679 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native },
680 { "onPauseNative", "(J)V", (void*)onPause_native },
681 { "onStopNative", "(J)V", (void*)onStop_native },
682 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native },
683 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native },
684 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native },
685 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
686 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
687 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native },
688 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native },
689 { "onInputQueueCreatedNative", "(JJ)V",
690 (void*)onInputQueueCreated_native },
691 { "onInputQueueDestroyedNative", "(JJ)V",
692 (void*)onInputQueueDestroyed_native },
693 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native },
694 };
695
696 static const char* const kNativeActivityPathName = "android/app/NativeActivity";
697
register_android_app_NativeActivity(JNIEnv * env)698 int register_android_app_NativeActivity(JNIEnv* env)
699 {
700 //ALOGD("register_android_app_NativeActivity");
701 jclass clazz = FindClassOrDie(env, kNativeActivityPathName);
702
703 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V");
704 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags",
705 "(II)V");
706 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat",
707 "(I)V");
708 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V");
709 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V");
710
711 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods));
712 }
713
714 } // namespace android
715