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