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