android_app_NativeActivity.cpp revision a95e4cb62f3642cb190d032dbf7dc40d9ecc6973
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_view_InputChannel.h" 22#include <android_runtime/AndroidRuntime.h> 23#include <android/native_activity.h> 24#include <ui/InputTransport.h> 25 26#include <dlfcn.h> 27 28namespace android 29{ 30 31struct NativeCode { 32 NativeCode(void* _dlhandle, android_activity_create_t* _createFunc) { 33 memset(&activity, sizeof(activity), 0); 34 memset(&callbacks, sizeof(callbacks), 0); 35 dlhandle = _dlhandle; 36 createActivityFunc = _createFunc; 37 surface = NULL; 38 inputChannel = NULL; 39 nativeInputQueue = NULL; 40 } 41 42 ~NativeCode() { 43 setSurface(NULL); 44 setInputChannel(NULL); 45 if (callbacks.onDestroy != NULL) { 46 callbacks.onDestroy(&activity); 47 } 48 if (dlhandle != NULL) { 49 dlclose(dlhandle); 50 } 51 } 52 53 void setSurface(jobject _surface) { 54 if (surface != NULL) { 55 activity.env->DeleteGlobalRef(surface); 56 } 57 if (_surface != NULL) { 58 surface = activity.env->NewGlobalRef(_surface); 59 } else { 60 surface = NULL; 61 } 62 } 63 64 status_t setInputChannel(jobject _channel) { 65 if (inputChannel != NULL) { 66 delete nativeInputQueue; 67 activity.env->DeleteGlobalRef(inputChannel); 68 } 69 inputChannel = NULL; 70 nativeInputQueue = NULL; 71 if (_channel != NULL) { 72 inputChannel = activity.env->NewGlobalRef(_channel); 73 sp<InputChannel> ic = 74 android_view_InputChannel_getInputChannel(activity.env, _channel); 75 if (ic != NULL) { 76 nativeInputQueue = new input_queue_t(ic); 77 if (nativeInputQueue->getConsumer().initialize() != android::OK) { 78 delete nativeInputQueue; 79 nativeInputQueue = NULL; 80 return UNKNOWN_ERROR; 81 } 82 } else { 83 return UNKNOWN_ERROR; 84 } 85 } 86 return OK; 87 } 88 89 android_activity_t activity; 90 android_activity_callbacks_t callbacks; 91 92 void* dlhandle; 93 android_activity_create_t* createActivityFunc; 94 95 jobject surface; 96 jobject inputChannel; 97 struct input_queue_t* nativeInputQueue; 98}; 99 100static jint 101loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path) 102{ 103 const char* pathStr = env->GetStringUTFChars(path, NULL); 104 NativeCode* code = NULL; 105 106 void* handle = dlopen(pathStr, RTLD_LAZY); 107 108 env->ReleaseStringUTFChars(path, pathStr); 109 110 if (handle != NULL) { 111 code = new NativeCode(handle, (android_activity_create_t*) 112 dlsym(handle, "android_onCreateActivity")); 113 if (code->createActivityFunc == NULL) { 114 LOGW("android_onCreateActivity not found"); 115 delete code; 116 return 0; 117 } 118 code->activity.callbacks = &code->callbacks; 119 code->activity.env = env; 120 code->activity.clazz = clazz; 121 code->createActivityFunc(&code->activity, NULL, 0); 122 } 123 124 return (jint)code; 125} 126 127static void 128unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle) 129{ 130 if (handle != 0) { 131 NativeCode* code = (NativeCode*)handle; 132 delete code; 133 } 134} 135 136static void 137onStart_native(JNIEnv* env, jobject clazz, jint handle) 138{ 139 if (handle != 0) { 140 NativeCode* code = (NativeCode*)handle; 141 if (code->callbacks.onStart != NULL) { 142 code->callbacks.onStart(&code->activity); 143 } 144 } 145} 146 147static void 148onResume_native(JNIEnv* env, jobject clazz, jint handle) 149{ 150 if (handle != 0) { 151 NativeCode* code = (NativeCode*)handle; 152 if (code->callbacks.onResume != NULL) { 153 code->callbacks.onResume(&code->activity); 154 } 155 } 156} 157 158static void 159onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle) 160{ 161 if (handle != 0) { 162 NativeCode* code = (NativeCode*)handle; 163 if (code->callbacks.onSaveInstanceState != NULL) { 164 size_t len = 0; 165 code->callbacks.onSaveInstanceState(&code->activity, &len); 166 } 167 } 168} 169 170static void 171onPause_native(JNIEnv* env, jobject clazz, jint handle) 172{ 173 if (handle != 0) { 174 NativeCode* code = (NativeCode*)handle; 175 if (code->callbacks.onPause != NULL) { 176 code->callbacks.onPause(&code->activity); 177 } 178 } 179} 180 181static void 182onStop_native(JNIEnv* env, jobject clazz, jint handle) 183{ 184 if (handle != 0) { 185 NativeCode* code = (NativeCode*)handle; 186 if (code->callbacks.onStop != NULL) { 187 code->callbacks.onStop(&code->activity); 188 } 189 } 190} 191 192static void 193onLowMemory_native(JNIEnv* env, jobject clazz, jint handle) 194{ 195 if (handle != 0) { 196 NativeCode* code = (NativeCode*)handle; 197 if (code->callbacks.onLowMemory != NULL) { 198 code->callbacks.onLowMemory(&code->activity); 199 } 200 } 201} 202 203static void 204onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused) 205{ 206 if (handle != 0) { 207 NativeCode* code = (NativeCode*)handle; 208 if (code->callbacks.onWindowFocusChanged != NULL) { 209 code->callbacks.onWindowFocusChanged(&code->activity, focused ? 1 : 0); 210 } 211 } 212} 213 214static void 215onSurfaceCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) 216{ 217 if (handle != 0) { 218 NativeCode* code = (NativeCode*)handle; 219 code->setSurface(surface); 220 if (code->callbacks.onSurfaceCreated != NULL) { 221 code->callbacks.onSurfaceCreated(&code->activity, 222 (android_surface_t*)code->surface); 223 } 224 } 225} 226 227static void 228onSurfaceChanged_native(JNIEnv* env, jobject clazz, jint handle, jobject surface, 229 jint format, jint width, jint height) 230{ 231 if (handle != 0) { 232 NativeCode* code = (NativeCode*)handle; 233 if (code->surface != NULL && code->callbacks.onSurfaceChanged != NULL) { 234 code->callbacks.onSurfaceChanged(&code->activity, 235 (android_surface_t*)code->surface, format, width, height); 236 } 237 } 238} 239 240static void 241onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) 242{ 243 if (handle != 0) { 244 NativeCode* code = (NativeCode*)handle; 245 if (code->surface != NULL && code->callbacks.onSurfaceDestroyed != NULL) { 246 code->callbacks.onSurfaceDestroyed(&code->activity, 247 (android_surface_t*)code->surface); 248 } 249 code->setSurface(NULL); 250 } 251} 252 253static void 254onInputChannelCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject channel) 255{ 256 if (handle != 0) { 257 NativeCode* code = (NativeCode*)handle; 258 status_t err = code->setInputChannel(channel); 259 if (err != OK) { 260 jniThrowException(env, "java/lang/IllegalStateException", 261 "Error setting input channel"); 262 return; 263 } 264 if (code->callbacks.onInputQueueCreated != NULL) { 265 code->callbacks.onInputQueueCreated(&code->activity, 266 code->nativeInputQueue); 267 } 268 } 269} 270 271static void 272onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject channel) 273{ 274 if (handle != 0) { 275 NativeCode* code = (NativeCode*)handle; 276 if (code->nativeInputQueue != NULL 277 && code->callbacks.onInputQueueDestroyed != NULL) { 278 code->callbacks.onInputQueueDestroyed(&code->activity, 279 code->nativeInputQueue); 280 } 281 code->setInputChannel(NULL); 282 } 283} 284 285static const JNINativeMethod g_methods[] = { 286 { "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native }, 287 { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native }, 288 { "onStartNative", "(I)V", (void*)onStart_native }, 289 { "onResumeNative", "(I)V", (void*)onResume_native }, 290 { "onSaveInstanceStateNative", "(I)V", (void*)onSaveInstanceState_native }, 291 { "onPauseNative", "(I)V", (void*)onPause_native }, 292 { "onStopNative", "(I)V", (void*)onStop_native }, 293 { "onLowMemoryNative", "(I)V", (void*)onLowMemory_native }, 294 { "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native }, 295 { "onSurfaceCreatedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceCreated_native }, 296 { "onSurfaceChangedNative", "(ILandroid/view/SurfaceHolder;III)V", (void*)onSurfaceChanged_native }, 297 { "onSurfaceDestroyedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceDestroyed_native }, 298 { "onInputChannelCreatedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelCreated_native }, 299 { "onInputChannelDestroyedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelDestroyed_native }, 300}; 301 302static const char* const kNativeActivityPathName = "android/app/NativeActivity"; 303 304int register_android_app_NativeActivity(JNIEnv* env) 305{ 306 //LOGD("register_android_app_NativeActivity"); 307 308 jclass clazz; 309 310 clazz = env->FindClass(kNativeActivityPathName); 311 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity"); 312 313 return AndroidRuntime::registerNativeMethods( 314 env, kNativeActivityPathName, 315 g_methods, NELEM(g_methods)); 316} 317 318} // namespace android 319