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 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 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 { 117 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 126 ~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 147 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 174 void android_NativeActivity_finish(ANativeActivity* activity) { 175 NativeCode* code = static_cast<NativeCode*>(activity); 176 write_work(code->mainWorkWrite, CMD_FINISH, 0); 177 } 178 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 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 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 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 */ 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 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 367 static jstring getDlError_native(JNIEnv* env, jobject clazz) { 368 return env->NewStringUTF(dlerror()); 369 } 370 371 static void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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