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