android_app_NativeActivity.cpp revision 69969e48f2bca9339662dddfacff0bbf6374ed7f
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 "JNIHelp.h"
21#include <android_runtime/AndroidRuntime.h>
22#include <android/native_activity.h>
23
24#include <dlfcn.h>
25
26namespace android
27{
28
29struct NativeCode {
30    android_activity_t activity;
31    android_activity_callbacks_t callbacks;
32
33    void* dlhandle;
34
35    android_activity_create_t* createActivityFunc;
36    void* clientContext;
37};
38
39static jint
40loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path)
41{
42    const char* pathStr = env->GetStringUTFChars(path, NULL);
43    NativeCode* code = NULL;
44
45    void* handle = dlopen(pathStr, RTLD_LAZY);
46
47    env->ReleaseStringUTFChars(path, pathStr);
48
49    if (handle != NULL) {
50        code = new NativeCode();
51        code->dlhandle = handle;
52        code->createActivityFunc = (android_activity_create_t*)
53                dlsym(handle, "android_onCreateActivity");
54        if (code->createActivityFunc == NULL) {
55            LOGW("android_onCreateActivity not found");
56            delete code;
57            dlclose(handle);
58            return 0;
59        }
60        memset(&code->activity, sizeof(code->activity), 0);
61        memset(&code->callbacks, sizeof(code->callbacks), 0);
62        code->activity.callbacks = &code->callbacks;
63        code->activity.env = env;
64        code->activity.clazz = clazz;
65        code->createActivityFunc(&code->activity, NULL, 0);
66    }
67
68    return (jint)code;
69}
70
71static void
72unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle)
73{
74    if (handle != 0) {
75        NativeCode* code = (NativeCode*)handle;
76        if (code->callbacks.onDestroy != NULL) {
77            code->callbacks.onDestroy(&code->activity);
78        }
79        dlclose(code->dlhandle);
80        delete code;
81    }
82}
83
84static void
85onStart_native(JNIEnv* env, jobject clazz, jint handle)
86{
87    if (handle != 0) {
88        NativeCode* code = (NativeCode*)handle;
89        if (code->callbacks.onStart != NULL) {
90            code->callbacks.onStart(&code->activity);
91        }
92    }
93}
94
95static void
96onResume_native(JNIEnv* env, jobject clazz, jint handle)
97{
98    if (handle != 0) {
99        NativeCode* code = (NativeCode*)handle;
100        if (code->callbacks.onResume != NULL) {
101            code->callbacks.onResume(&code->activity);
102        }
103    }
104}
105
106static void
107onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle)
108{
109    if (handle != 0) {
110        NativeCode* code = (NativeCode*)handle;
111        if (code->callbacks.onSaveInstanceState != NULL) {
112            size_t len = 0;
113            code->callbacks.onSaveInstanceState(&code->activity, &len);
114        }
115    }
116}
117
118static void
119onPause_native(JNIEnv* env, jobject clazz, jint handle)
120{
121    if (handle != 0) {
122        NativeCode* code = (NativeCode*)handle;
123        if (code->callbacks.onPause != NULL) {
124            code->callbacks.onPause(&code->activity);
125        }
126    }
127}
128
129static void
130onStop_native(JNIEnv* env, jobject clazz, jint handle)
131{
132    if (handle != 0) {
133        NativeCode* code = (NativeCode*)handle;
134        if (code->callbacks.onStop != NULL) {
135            code->callbacks.onStop(&code->activity);
136        }
137    }
138}
139
140static void
141onLowMemory_native(JNIEnv* env, jobject clazz, jint handle)
142{
143    if (handle != 0) {
144        NativeCode* code = (NativeCode*)handle;
145        if (code->callbacks.onLowMemory != NULL) {
146            code->callbacks.onLowMemory(&code->activity);
147        }
148    }
149}
150
151static void
152onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused)
153{
154    if (handle != 0) {
155        NativeCode* code = (NativeCode*)handle;
156        if (code->callbacks.onWindowFocusChanged != NULL) {
157            code->callbacks.onWindowFocusChanged(&code->activity, focused ? 1 : 0);
158        }
159    }
160}
161
162static const JNINativeMethod g_methods[] = {
163    { "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native },
164    { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
165    { "onStartNative", "(I)V", (void*)onStart_native },
166    { "onResumeNative", "(I)V", (void*)onResume_native },
167    { "onSaveInstanceStateNative", "(I)V", (void*)onSaveInstanceState_native },
168    { "onPauseNative", "(I)V", (void*)onPause_native },
169    { "onStopNative", "(I)V", (void*)onStop_native },
170    { "onLowMemoryNative", "(I)V", (void*)onLowMemory_native },
171    { "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native },
172};
173
174static const char* const kNativeActivityPathName = "android/app/NativeActivity";
175
176int register_android_app_NativeActivity(JNIEnv* env)
177{
178    //LOGD("register_android_app_NativeActivity");
179
180    jclass clazz;
181
182    clazz = env->FindClass(kNativeActivityPathName);
183    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity");
184
185    return AndroidRuntime::registerNativeMethods(
186        env, kNativeActivityPathName,
187        g_methods, NELEM(g_methods));
188}
189
190}
191