android_app_NativeActivity.cpp revision 2e9f93e8db509d5236229dc8540e0904c5dbb9f5
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, ANativeActivity_createFunc* _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 AInputQueue(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 ANativeActivity activity; 90 ANativeActivityCallbacks callbacks; 91 92 void* dlhandle; 93 ANativeActivity_createFunc* createActivityFunc; 94 95 jobject surface; 96 jobject inputChannel; 97 struct AInputQueue* 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, (ANativeActivity_createFunc*) 112 dlsym(handle, "ANativeActivity_onCreate")); 113 if (code->createActivityFunc == NULL) { 114 LOGW("ANativeActivity_onCreate not found"); 115 delete code; 116 return 0; 117 } 118 code->activity.callbacks = &code->callbacks; 119 if (env->GetJavaVM(&code->activity.vm) < 0) { 120 LOGW("NativeActivity GetJavaVM failed"); 121 delete code; 122 return 0; 123 } 124 code->activity.env = env; 125 code->activity.clazz = clazz; 126 code->createActivityFunc(&code->activity, NULL, 0); 127 } 128 129 return (jint)code; 130} 131 132static void 133unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle) 134{ 135 if (handle != 0) { 136 NativeCode* code = (NativeCode*)handle; 137 delete code; 138 } 139} 140 141static void 142onStart_native(JNIEnv* env, jobject clazz, jint handle) 143{ 144 if (handle != 0) { 145 NativeCode* code = (NativeCode*)handle; 146 if (code->callbacks.onStart != NULL) { 147 code->callbacks.onStart(&code->activity); 148 } 149 } 150} 151 152static void 153onResume_native(JNIEnv* env, jobject clazz, jint handle) 154{ 155 if (handle != 0) { 156 NativeCode* code = (NativeCode*)handle; 157 if (code->callbacks.onResume != NULL) { 158 code->callbacks.onResume(&code->activity); 159 } 160 } 161} 162 163static void 164onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle) 165{ 166 if (handle != 0) { 167 NativeCode* code = (NativeCode*)handle; 168 if (code->callbacks.onSaveInstanceState != NULL) { 169 size_t len = 0; 170 code->callbacks.onSaveInstanceState(&code->activity, &len); 171 } 172 } 173} 174 175static void 176onPause_native(JNIEnv* env, jobject clazz, jint handle) 177{ 178 if (handle != 0) { 179 NativeCode* code = (NativeCode*)handle; 180 if (code->callbacks.onPause != NULL) { 181 code->callbacks.onPause(&code->activity); 182 } 183 } 184} 185 186static void 187onStop_native(JNIEnv* env, jobject clazz, jint handle) 188{ 189 if (handle != 0) { 190 NativeCode* code = (NativeCode*)handle; 191 if (code->callbacks.onStop != NULL) { 192 code->callbacks.onStop(&code->activity); 193 } 194 } 195} 196 197static void 198onLowMemory_native(JNIEnv* env, jobject clazz, jint handle) 199{ 200 if (handle != 0) { 201 NativeCode* code = (NativeCode*)handle; 202 if (code->callbacks.onLowMemory != NULL) { 203 code->callbacks.onLowMemory(&code->activity); 204 } 205 } 206} 207 208static void 209onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused) 210{ 211 if (handle != 0) { 212 NativeCode* code = (NativeCode*)handle; 213 if (code->callbacks.onWindowFocusChanged != NULL) { 214 code->callbacks.onWindowFocusChanged(&code->activity, focused ? 1 : 0); 215 } 216 } 217} 218 219static void 220onSurfaceCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) 221{ 222 if (handle != 0) { 223 NativeCode* code = (NativeCode*)handle; 224 code->setSurface(surface); 225 if (code->callbacks.onSurfaceCreated != NULL) { 226 code->callbacks.onSurfaceCreated(&code->activity, 227 (ASurfaceHolder*)code->surface); 228 } 229 } 230} 231 232static void 233onSurfaceChanged_native(JNIEnv* env, jobject clazz, jint handle, jobject surface, 234 jint format, jint width, jint height) 235{ 236 if (handle != 0) { 237 NativeCode* code = (NativeCode*)handle; 238 if (code->surface != NULL && code->callbacks.onSurfaceChanged != NULL) { 239 code->callbacks.onSurfaceChanged(&code->activity, 240 (ASurfaceHolder*)code->surface, format, width, height); 241 } 242 } 243} 244 245static void 246onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surface) 247{ 248 if (handle != 0) { 249 NativeCode* code = (NativeCode*)handle; 250 if (code->surface != NULL && code->callbacks.onSurfaceDestroyed != NULL) { 251 code->callbacks.onSurfaceDestroyed(&code->activity, 252 (ASurfaceHolder*)code->surface); 253 } 254 code->setSurface(NULL); 255 } 256} 257 258static void 259onInputChannelCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject channel) 260{ 261 if (handle != 0) { 262 NativeCode* code = (NativeCode*)handle; 263 status_t err = code->setInputChannel(channel); 264 if (err != OK) { 265 jniThrowException(env, "java/lang/IllegalStateException", 266 "Error setting input channel"); 267 return; 268 } 269 if (code->callbacks.onInputQueueCreated != NULL) { 270 code->callbacks.onInputQueueCreated(&code->activity, 271 code->nativeInputQueue); 272 } 273 } 274} 275 276static void 277onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject channel) 278{ 279 if (handle != 0) { 280 NativeCode* code = (NativeCode*)handle; 281 if (code->nativeInputQueue != NULL 282 && code->callbacks.onInputQueueDestroyed != NULL) { 283 code->callbacks.onInputQueueDestroyed(&code->activity, 284 code->nativeInputQueue); 285 } 286 code->setInputChannel(NULL); 287 } 288} 289 290static const JNINativeMethod g_methods[] = { 291 { "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native }, 292 { "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native }, 293 { "onStartNative", "(I)V", (void*)onStart_native }, 294 { "onResumeNative", "(I)V", (void*)onResume_native }, 295 { "onSaveInstanceStateNative", "(I)V", (void*)onSaveInstanceState_native }, 296 { "onPauseNative", "(I)V", (void*)onPause_native }, 297 { "onStopNative", "(I)V", (void*)onStop_native }, 298 { "onLowMemoryNative", "(I)V", (void*)onLowMemory_native }, 299 { "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native }, 300 { "onSurfaceCreatedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceCreated_native }, 301 { "onSurfaceChangedNative", "(ILandroid/view/SurfaceHolder;III)V", (void*)onSurfaceChanged_native }, 302 { "onSurfaceDestroyedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceDestroyed_native }, 303 { "onInputChannelCreatedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelCreated_native }, 304 { "onInputChannelDestroyedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelDestroyed_native }, 305}; 306 307static const char* const kNativeActivityPathName = "android/app/NativeActivity"; 308 309int register_android_app_NativeActivity(JNIEnv* env) 310{ 311 //LOGD("register_android_app_NativeActivity"); 312 313 jclass clazz; 314 315 clazz = env->FindClass(kNativeActivityPathName); 316 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity"); 317 318 return AndroidRuntime::registerNativeMethods( 319 env, kNativeActivityPathName, 320 g_methods, NELEM(g_methods)); 321} 322 323} // namespace android 324