Home | History | Annotate | Download | only in jni
      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     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 
    389 static 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 
    395 static void
    396 unloadNativeCode_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 
    407 static void
    408 onStart_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 
    421 static void
    422 onResume_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 
    435 static jbyteArray
    436 onSaveInstanceState_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 
    464 static void
    465 onPause_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 
    478 static void
    479 onStop_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 
    492 static void
    493 onConfigurationChanged_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 
    506 static void
    507 onLowMemory_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 
    520 static void
    521 onWindowFocusChanged_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 
    534 static void
    535 onSurfaceCreated_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 
    550 static 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 
    556 static void
    557 onSurfaceChanged_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 
    599 static void
    600 onSurfaceRedrawNeeded_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 
    613 static void
    614 onSurfaceDestroyed_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 
    629 static void
    630 onInputQueueCreated_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 
    644 static void
    645 onInputQueueDestroyed_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 
    659 static void
    660 onContentRectChanged_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 
    679 static 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 
    704 static const char* const kNativeActivityPathName = "android/app/NativeActivity";
    705 
    706 int 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