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 54namespace android 55{ 56 57static const bool kLogTrace = false; 58 59static struct { 60 jmethodID finish; 61 jmethodID setWindowFlags; 62 jmethodID setWindowFormat; 63 jmethodID showIme; 64 jmethodID hideIme; 65} gNativeActivityClassInfo; 66 67// ------------------------------------------------------------------------ 68 69struct ActivityWork { 70 int32_t cmd; 71 int32_t arg1; 72 int32_t arg2; 73}; 74 75enum { 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 83static 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 93restart: 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 105static 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 */ 118struct 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 185void android_NativeActivity_finish(ANativeActivity* activity) { 186 NativeCode* code = static_cast<NativeCode*>(activity); 187 write_work(code->mainWorkWrite, CMD_FINISH, 0); 188} 189 190void 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 196void 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 202void 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 208void 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 */ 219static 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 269static thread_local std::string g_error_msg; 270 271static jlong 272loadNativeCode_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 void* handle = OpenNativeLibrary(env, 285 sdkVersion, 286 pathStr.c_str(), 287 classLoader, 288 libraryPath, 289 &needs_native_bridge, 290 &g_error_msg); 291 292 if (handle == nullptr) { 293 ALOGW("NativeActivity LoadNativeLibrary(\"%s\") failed: %s", 294 pathStr.c_str(), 295 g_error_msg.c_str()); 296 return 0; 297 } 298 299 void* funcPtr = NULL; 300 const char* funcStr = env->GetStringUTFChars(funcName, NULL); 301 if (needs_native_bridge) { 302 funcPtr = NativeBridgeGetTrampoline(handle, funcStr, NULL, 0); 303 } else { 304 funcPtr = dlsym(handle, funcStr); 305 } 306 307 code.reset(new NativeCode(handle, (ANativeActivity_createFunc*)funcPtr)); 308 env->ReleaseStringUTFChars(funcName, funcStr); 309 310 if (code->createActivityFunc == NULL) { 311 g_error_msg = needs_native_bridge ? NativeBridgeGetError() : dlerror(); 312 ALOGW("ANativeActivity_onCreate not found: %s", g_error_msg.c_str()); 313 return 0; 314 } 315 316 code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue); 317 if (code->messageQueue == NULL) { 318 g_error_msg = "Unable to retrieve native MessageQueue"; 319 ALOGW("%s", g_error_msg.c_str()); 320 return 0; 321 } 322 323 int msgpipe[2]; 324 if (pipe(msgpipe)) { 325 g_error_msg = android::base::StringPrintf("could not create pipe: %s", strerror(errno)); 326 ALOGW("%s", g_error_msg.c_str()); 327 return 0; 328 } 329 code->mainWorkRead = msgpipe[0]; 330 code->mainWorkWrite = msgpipe[1]; 331 int result = fcntl(code->mainWorkRead, F_SETFL, O_NONBLOCK); 332 SLOGW_IF(result != 0, "Could not make main work read pipe " 333 "non-blocking: %s", strerror(errno)); 334 result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK); 335 SLOGW_IF(result != 0, "Could not make main work write pipe " 336 "non-blocking: %s", strerror(errno)); 337 code->messageQueue->getLooper()->addFd( 338 code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code.get()); 339 340 code->ANativeActivity::callbacks = &code->callbacks; 341 if (env->GetJavaVM(&code->vm) < 0) { 342 g_error_msg = "NativeActivity GetJavaVM failed"; 343 ALOGW("%s", g_error_msg.c_str()); 344 return 0; 345 } 346 code->env = env; 347 code->clazz = env->NewGlobalRef(clazz); 348 349 const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL); 350 code->internalDataPathObj = dirStr; 351 code->internalDataPath = code->internalDataPathObj.string(); 352 env->ReleaseStringUTFChars(internalDataDir, dirStr); 353 354 if (externalDataDir != NULL) { 355 dirStr = env->GetStringUTFChars(externalDataDir, NULL); 356 code->externalDataPathObj = dirStr; 357 env->ReleaseStringUTFChars(externalDataDir, dirStr); 358 } 359 code->externalDataPath = code->externalDataPathObj.string(); 360 361 code->sdkVersion = sdkVersion; 362 363 code->javaAssetManager = env->NewGlobalRef(jAssetMgr); 364 code->assetManager = NdkAssetManagerForJavaObject(env, jAssetMgr); 365 366 if (obbDir != NULL) { 367 dirStr = env->GetStringUTFChars(obbDir, NULL); 368 code->obbPathObj = dirStr; 369 env->ReleaseStringUTFChars(obbDir, dirStr); 370 } 371 code->obbPath = code->obbPathObj.string(); 372 373 jbyte* rawSavedState = NULL; 374 jsize rawSavedSize = 0; 375 if (savedState != NULL) { 376 rawSavedState = env->GetByteArrayElements(savedState, NULL); 377 rawSavedSize = env->GetArrayLength(savedState); 378 } 379 380 code->createActivityFunc(code.get(), rawSavedState, rawSavedSize); 381 382 if (rawSavedState != NULL) { 383 env->ReleaseByteArrayElements(savedState, rawSavedState, 0); 384 } 385 386 return (jlong)code.release(); 387} 388 389static jstring getDlError_native(JNIEnv* env, jobject clazz) { 390 jstring result = env->NewStringUTF(g_error_msg.c_str()); 391 g_error_msg.clear(); 392 return result; 393} 394 395static void 396unloadNativeCode_native(JNIEnv* env, jobject clazz, jlong handle) 397{ 398 if (kLogTrace) { 399 ALOGD("unloadNativeCode_native"); 400 } 401 if (handle != 0) { 402 NativeCode* code = (NativeCode*)handle; 403 delete code; 404 } 405} 406 407static void 408onStart_native(JNIEnv* env, jobject clazz, jlong handle) 409{ 410 if (kLogTrace) { 411 ALOGD("onStart_native"); 412 } 413 if (handle != 0) { 414 NativeCode* code = (NativeCode*)handle; 415 if (code->callbacks.onStart != NULL) { 416 code->callbacks.onStart(code); 417 } 418 } 419} 420 421static void 422onResume_native(JNIEnv* env, jobject clazz, jlong handle) 423{ 424 if (kLogTrace) { 425 ALOGD("onResume_native"); 426 } 427 if (handle != 0) { 428 NativeCode* code = (NativeCode*)handle; 429 if (code->callbacks.onResume != NULL) { 430 code->callbacks.onResume(code); 431 } 432 } 433} 434 435static jbyteArray 436onSaveInstanceState_native(JNIEnv* env, jobject clazz, jlong handle) 437{ 438 if (kLogTrace) { 439 ALOGD("onSaveInstanceState_native"); 440 } 441 442 jbyteArray array = NULL; 443 444 if (handle != 0) { 445 NativeCode* code = (NativeCode*)handle; 446 if (code->callbacks.onSaveInstanceState != NULL) { 447 size_t len = 0; 448 jbyte* state = (jbyte*)code->callbacks.onSaveInstanceState(code, &len); 449 if (len > 0) { 450 array = env->NewByteArray(len); 451 if (array != NULL) { 452 env->SetByteArrayRegion(array, 0, len, state); 453 } 454 } 455 if (state != NULL) { 456 free(state); 457 } 458 } 459 } 460 461 return array; 462} 463 464static void 465onPause_native(JNIEnv* env, jobject clazz, jlong handle) 466{ 467 if (kLogTrace) { 468 ALOGD("onPause_native"); 469 } 470 if (handle != 0) { 471 NativeCode* code = (NativeCode*)handle; 472 if (code->callbacks.onPause != NULL) { 473 code->callbacks.onPause(code); 474 } 475 } 476} 477 478static void 479onStop_native(JNIEnv* env, jobject clazz, jlong handle) 480{ 481 if (kLogTrace) { 482 ALOGD("onStop_native"); 483 } 484 if (handle != 0) { 485 NativeCode* code = (NativeCode*)handle; 486 if (code->callbacks.onStop != NULL) { 487 code->callbacks.onStop(code); 488 } 489 } 490} 491 492static void 493onConfigurationChanged_native(JNIEnv* env, jobject clazz, jlong handle) 494{ 495 if (kLogTrace) { 496 ALOGD("onConfigurationChanged_native"); 497 } 498 if (handle != 0) { 499 NativeCode* code = (NativeCode*)handle; 500 if (code->callbacks.onConfigurationChanged != NULL) { 501 code->callbacks.onConfigurationChanged(code); 502 } 503 } 504} 505 506static void 507onLowMemory_native(JNIEnv* env, jobject clazz, jlong handle) 508{ 509 if (kLogTrace) { 510 ALOGD("onLowMemory_native"); 511 } 512 if (handle != 0) { 513 NativeCode* code = (NativeCode*)handle; 514 if (code->callbacks.onLowMemory != NULL) { 515 code->callbacks.onLowMemory(code); 516 } 517 } 518} 519 520static void 521onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jlong handle, jboolean focused) 522{ 523 if (kLogTrace) { 524 ALOGD("onWindowFocusChanged_native"); 525 } 526 if (handle != 0) { 527 NativeCode* code = (NativeCode*)handle; 528 if (code->callbacks.onWindowFocusChanged != NULL) { 529 code->callbacks.onWindowFocusChanged(code, focused ? 1 : 0); 530 } 531 } 532} 533 534static void 535onSurfaceCreated_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface) 536{ 537 if (kLogTrace) { 538 ALOGD("onSurfaceCreated_native"); 539 } 540 if (handle != 0) { 541 NativeCode* code = (NativeCode*)handle; 542 code->setSurface(surface); 543 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) { 544 code->callbacks.onNativeWindowCreated(code, 545 code->nativeWindow.get()); 546 } 547 } 548} 549 550static int32_t getWindowProp(ANativeWindow* window, int what) { 551 int value; 552 int res = window->query(window, what, &value); 553 return res < 0 ? res : value; 554} 555 556static void 557onSurfaceChanged_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface, 558 jint format, jint width, jint height) 559{ 560 if (kLogTrace) { 561 ALOGD("onSurfaceChanged_native"); 562 } 563 if (handle != 0) { 564 NativeCode* code = (NativeCode*)handle; 565 sp<ANativeWindow> oldNativeWindow = code->nativeWindow; 566 code->setSurface(surface); 567 if (oldNativeWindow != code->nativeWindow) { 568 if (oldNativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) { 569 code->callbacks.onNativeWindowDestroyed(code, 570 oldNativeWindow.get()); 571 } 572 if (code->nativeWindow != NULL) { 573 if (code->callbacks.onNativeWindowCreated != NULL) { 574 code->callbacks.onNativeWindowCreated(code, 575 code->nativeWindow.get()); 576 } 577 code->lastWindowWidth = getWindowProp(code->nativeWindow.get(), 578 NATIVE_WINDOW_WIDTH); 579 code->lastWindowHeight = getWindowProp(code->nativeWindow.get(), 580 NATIVE_WINDOW_HEIGHT); 581 } 582 } else { 583 // Maybe it resized? 584 int32_t newWidth = getWindowProp(code->nativeWindow.get(), 585 NATIVE_WINDOW_WIDTH); 586 int32_t newHeight = getWindowProp(code->nativeWindow.get(), 587 NATIVE_WINDOW_HEIGHT); 588 if (newWidth != code->lastWindowWidth 589 || newHeight != code->lastWindowHeight) { 590 if (code->callbacks.onNativeWindowResized != NULL) { 591 code->callbacks.onNativeWindowResized(code, 592 code->nativeWindow.get()); 593 } 594 } 595 } 596 } 597} 598 599static void 600onSurfaceRedrawNeeded_native(JNIEnv* env, jobject clazz, jlong handle) 601{ 602 if (kLogTrace) { 603 ALOGD("onSurfaceRedrawNeeded_native"); 604 } 605 if (handle != 0) { 606 NativeCode* code = (NativeCode*)handle; 607 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowRedrawNeeded != NULL) { 608 code->callbacks.onNativeWindowRedrawNeeded(code, code->nativeWindow.get()); 609 } 610 } 611} 612 613static void 614onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jobject surface) 615{ 616 if (kLogTrace) { 617 ALOGD("onSurfaceDestroyed_native"); 618 } 619 if (handle != 0) { 620 NativeCode* code = (NativeCode*)handle; 621 if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) { 622 code->callbacks.onNativeWindowDestroyed(code, 623 code->nativeWindow.get()); 624 } 625 code->setSurface(NULL); 626 } 627} 628 629static void 630onInputQueueCreated_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr) 631{ 632 if (kLogTrace) { 633 ALOGD("onInputChannelCreated_native"); 634 } 635 if (handle != 0) { 636 NativeCode* code = (NativeCode*)handle; 637 if (code->callbacks.onInputQueueCreated != NULL) { 638 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr); 639 code->callbacks.onInputQueueCreated(code, queue); 640 } 641 } 642} 643 644static void 645onInputQueueDestroyed_native(JNIEnv* env, jobject clazz, jlong handle, jlong queuePtr) 646{ 647 if (kLogTrace) { 648 ALOGD("onInputChannelDestroyed_native"); 649 } 650 if (handle != 0) { 651 NativeCode* code = (NativeCode*)handle; 652 if (code->callbacks.onInputQueueDestroyed != NULL) { 653 AInputQueue* queue = reinterpret_cast<AInputQueue*>(queuePtr); 654 code->callbacks.onInputQueueDestroyed(code, queue); 655 } 656 } 657} 658 659static void 660onContentRectChanged_native(JNIEnv* env, jobject clazz, jlong handle, 661 jint x, jint y, jint w, jint h) 662{ 663 if (kLogTrace) { 664 ALOGD("onContentRectChanged_native"); 665 } 666 if (handle != 0) { 667 NativeCode* code = (NativeCode*)handle; 668 if (code->callbacks.onContentRectChanged != NULL) { 669 ARect rect; 670 rect.left = x; 671 rect.top = y; 672 rect.right = x+w; 673 rect.bottom = y+h; 674 code->callbacks.onContentRectChanged(code, &rect); 675 } 676 } 677} 678 679static const JNINativeMethod g_methods[] = { 680 { "loadNativeCode", 681 "(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", 682 (void*)loadNativeCode_native }, 683 { "getDlError", "()Ljava/lang/String;", (void*) getDlError_native }, 684 { "unloadNativeCode", "(J)V", (void*)unloadNativeCode_native }, 685 { "onStartNative", "(J)V", (void*)onStart_native }, 686 { "onResumeNative", "(J)V", (void*)onResume_native }, 687 { "onSaveInstanceStateNative", "(J)[B", (void*)onSaveInstanceState_native }, 688 { "onPauseNative", "(J)V", (void*)onPause_native }, 689 { "onStopNative", "(J)V", (void*)onStop_native }, 690 { "onConfigurationChangedNative", "(J)V", (void*)onConfigurationChanged_native }, 691 { "onLowMemoryNative", "(J)V", (void*)onLowMemory_native }, 692 { "onWindowFocusChangedNative", "(JZ)V", (void*)onWindowFocusChanged_native }, 693 { "onSurfaceCreatedNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceCreated_native }, 694 { "onSurfaceChangedNative", "(JLandroid/view/Surface;III)V", (void*)onSurfaceChanged_native }, 695 { "onSurfaceRedrawNeededNative", "(JLandroid/view/Surface;)V", (void*)onSurfaceRedrawNeeded_native }, 696 { "onSurfaceDestroyedNative", "(J)V", (void*)onSurfaceDestroyed_native }, 697 { "onInputQueueCreatedNative", "(JJ)V", 698 (void*)onInputQueueCreated_native }, 699 { "onInputQueueDestroyedNative", "(JJ)V", 700 (void*)onInputQueueDestroyed_native }, 701 { "onContentRectChangedNative", "(JIIII)V", (void*)onContentRectChanged_native }, 702}; 703 704static const char* const kNativeActivityPathName = "android/app/NativeActivity"; 705 706int register_android_app_NativeActivity(JNIEnv* env) 707{ 708 //ALOGD("register_android_app_NativeActivity"); 709 jclass clazz = FindClassOrDie(env, kNativeActivityPathName); 710 711 gNativeActivityClassInfo.finish = GetMethodIDOrDie(env, clazz, "finish", "()V"); 712 gNativeActivityClassInfo.setWindowFlags = GetMethodIDOrDie(env, clazz, "setWindowFlags", 713 "(II)V"); 714 gNativeActivityClassInfo.setWindowFormat = GetMethodIDOrDie(env, clazz, "setWindowFormat", 715 "(I)V"); 716 gNativeActivityClassInfo.showIme = GetMethodIDOrDie(env, clazz, "showIme", "(I)V"); 717 gNativeActivityClassInfo.hideIme = GetMethodIDOrDie(env, clazz, "hideIme", "(I)V"); 718 719 return RegisterMethodsOrDie(env, kNativeActivityPathName, g_methods, NELEM(g_methods)); 720} 721 722} // namespace android 723