void message_dispatcher::reset_queue_locked() { if (m_iqueue) { AInputQueue_detachLooper(m_iqueue); LOGI("%s:%d> detaching looper from queue %p\n", __FILE__, __LINE__, m_iqueue); } }
static void cui_onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) { CUI_DEBUG("cui_onInputQueueCreated\n"); if ((activity == NULL) || (queue == NULL)) { CUI_DEBUG("InputQueueCreated param error\n"); return; } struct cui_app * this_app = NULL; this_app = (struct cui_app *)activity->instance; pthread_mutex_lock(&this_app->mutex_lock); if(this_app == NULL) { CUI_DEBUG("this app is not init\n"); return; } if (this_app->input_queue != NULL) { AInputQueue_detachLooper(this_app->input_queue); } this_app->input_queue = queue; if (this_app->input_queue != NULL) { CUI_DEBUG("Attaching input queue to looper"); AInputQueue_attachLooper(this_app->input_queue, this_app->looper, 1, looper_callback, this_app); } pthread_mutex_unlock(&this_app->mutex_lock); }
void *cxAndroid::AndroidEntry(void *data) { cxAndroid *app = (cxAndroid *)data; AConfiguration_fromAssetManager(app->config, app->activity->assetManager); app->cmd.id = LOOPER_ID_MAIN; app->cmd.app = app; app->cmd.process = cxAndroid::cxAndroidExec; app->input.id = LOOPER_ID_INPUT; app->input.app = app; app->input.process = cxAndroid::cxAndroidInputExec; app->looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(app->looper, app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,&app->cmd); pthread_mutex_lock(&app->mutex); app->running = true; pthread_cond_broadcast(&app->cond); pthread_mutex_unlock(&app->mutex); app->cxAndroidMain(); pthread_mutex_lock(&app->mutex); if (app->inputQueue != NULL) { AInputQueue_detachLooper(app->inputQueue); app->inputQueue = NULL; } AConfiguration_delete(app->config); app->config = NULL; app->destroyed = true; pthread_cond_broadcast(&app->cond); pthread_mutex_unlock(&app->mutex); return data; }
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { switch (cmd) { case APP_CMD_INPUT_CHANGED: LOGV("APP_CMD_INPUT_CHANGED\n"); pthread_mutex_lock(&android_app->mutex); if (android_app->inputQueue != NULL) { AInputQueue_detachLooper(android_app->inputQueue); } android_app->inputQueue = android_app->pendingInputQueue; if (android_app->inputQueue != NULL) { LOGV("Attaching input queue to looper"); AInputQueue_attachLooper(android_app->inputQueue, android_app->looper, LOOPER_ID_INPUT, NULL, &android_app->inputPollSource); } pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_INIT_WINDOW: LOGV("APP_CMD_INIT_WINDOW\n"); pthread_mutex_lock(&android_app->mutex); android_app->window = android_app->pendingWindow; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_TERM_WINDOW: LOGV("APP_CMD_TERM_WINDOW\n"); pthread_cond_broadcast(&android_app->cond); break; case APP_CMD_RESUME: case APP_CMD_START: case APP_CMD_PAUSE: case APP_CMD_STOP: LOGV("activityState=%d\n", cmd); pthread_mutex_lock(&android_app->mutex); android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_CONFIG_CHANGED: LOGV("APP_CMD_CONFIG_CHANGED\n"); AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); print_cur_config(android_app); break; case APP_CMD_DESTROY: LOGV("APP_CMD_DESTROY\n"); android_app->destroyRequested = 1; break; } }
static void android_app_destroy(struct android_app* android_app) { free_saved_state(android_app); pthread_mutex_lock(&android_app->mutex); if (android_app->inputQueue != NULL) { AInputQueue_detachLooper(android_app->inputQueue); } AConfiguration_delete(android_app->config); android_app->destroyed = 1; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); // Can't touch android_app object after this. }
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) { // Retrieve our activity states from the activity instance sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); // Detach the input queue { sf::Lock lock(states->mutex); states->inputQueue = NULL; AInputQueue_detachLooper(queue); } }
static void android_app_destroy ( struct android_app* android_app ) { LOGV ( "android_app_destroy!" ); free_saved_state ( android_app ); pthread_mutex_lock ( &android_app->mutex ); if ( android_app->inputQueue != NULL ) { AInputQueue_detachLooper ( android_app->inputQueue ); } AConfiguration_delete ( android_app->config ); android_app->destroyed = 1; pthread_cond_broadcast ( &android_app->cond ); pthread_mutex_unlock ( &android_app->mutex ); // 이후에 android_app 개체를 터치할 수 없습니다. }
static void frontend_android_deinit(void *data) { struct android_app* android_app = (struct android_app*)data; if (!android_app) return; RARCH_LOG("Deinitializing RetroArch ...\n"); android_app->activityState = APP_CMD_DEAD; if (android_app->inputQueue) { RARCH_LOG("Detaching Android input queue looper ...\n"); AInputQueue_detachLooper(android_app->inputQueue); } }
void cxAndroid::cxAndroidPreExec(cxAndroid *app, int8_t cmd) { switch (cmd) { case APP_CMD_INPUT_CHANGED:{ pthread_mutex_lock(&app->mutex); if (app->inputQueue != NULL) { AInputQueue_detachLooper(app->inputQueue); } app->inputQueue = app->pendingInputQueue; if (app->inputQueue != NULL) { AInputQueue_attachLooper(app->inputQueue,app->looper, LOOPER_ID_INPUT, NULL,&app->input); } pthread_cond_broadcast(&app->cond); pthread_mutex_unlock(&app->mutex); break; } case APP_CMD_INIT_WINDOW:{ pthread_mutex_lock(&app->mutex); app->window = app->pendingWindow; pthread_cond_broadcast(&app->cond); pthread_mutex_unlock(&app->mutex); break; } case APP_CMD_TERM_WINDOW:{ pthread_cond_broadcast(&app->cond); break; } case APP_CMD_RESUME: case APP_CMD_START: case APP_CMD_PAUSE: case APP_CMD_STOP:{ pthread_mutex_lock(&app->mutex); app->activityState = cmd; pthread_cond_broadcast(&app->cond); pthread_mutex_unlock(&app->mutex); break; } case APP_CMD_CONFIG_CHANGED:{ AConfiguration_fromAssetManager(app->config,app->activity->assetManager); break; } case APP_CMD_DESTROY:{ app->destroyReq = true; break; } } }
static void frontend_android_deinit(void *data) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; RARCH_LOG("Deinitializing RetroArch ...\n"); android_app->activityState = APP_CMD_DEAD; JNIEnv *env = jni_thread_getenv(); if (env && android_app->onRetroArchExit) CALL_VOID_METHOD(env, android_app->activity->clazz, android_app->onRetroArchExit); if (android_app->inputQueue) { RARCH_LOG("Detaching Android input queue looper ...\n"); AInputQueue_detachLooper(android_app->inputQueue); } }
void engine_handle_cmd(void *data) { struct android_app *android_app = (struct android_app*)g_android; int8_t cmd; if (read(android_app->msgread, &cmd, sizeof(cmd)) != sizeof(cmd)) cmd = -1; switch (cmd) { case APP_CMD_INPUT_CHANGED: slock_lock(android_app->mutex); if (android_app->inputQueue) AInputQueue_detachLooper(android_app->inputQueue); android_app->inputQueue = android_app->pendingInputQueue; if (android_app->inputQueue) { RARCH_LOG("Attaching input queue to looper"); AInputQueue_attachLooper(android_app->inputQueue, android_app->looper, LOOPER_ID_INPUT, NULL, NULL); } scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); break; case APP_CMD_INIT_WINDOW: slock_lock(android_app->mutex); android_app->window = android_app->pendingWindow; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); if (g_extern.is_paused) rarch_reinit_drivers(); break; case APP_CMD_RESUME: slock_lock(android_app->mutex); android_app->activityState = cmd; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); break; case APP_CMD_START: slock_lock(android_app->mutex); android_app->activityState = cmd; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); break; case APP_CMD_PAUSE: slock_lock(android_app->mutex); android_app->activityState = cmd; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); if (!g_extern.system.shutdown) { RARCH_LOG("Pausing RetroArch.\n"); g_extern.is_paused = true; } break; case APP_CMD_STOP: slock_lock(android_app->mutex); android_app->activityState = cmd; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); break; case APP_CMD_CONFIG_CHANGED: break; case APP_CMD_TERM_WINDOW: slock_lock(android_app->mutex); /* The window is being hidden or closed, clean it up. */ /* terminate display/EGL context here */ //RARCH_WARN("Window is terminated outside PAUSED state.\n"); android_app->window = NULL; scond_broadcast(android_app->cond); slock_unlock(android_app->mutex); break; case APP_CMD_GAINED_FOCUS: g_extern.is_paused = false; if ((android_app->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)) && android_app->accelerometerSensor == NULL && driver.input_data) android_input_set_sensor_state(driver.input_data, 0, RETRO_SENSOR_ACCELEROMETER_ENABLE, android_app->accelerometer_event_rate); break; case APP_CMD_LOST_FOCUS: // Avoid draining battery while app is not being used if ((android_app->sensor_state_mask & (1ULL << RETRO_SENSOR_ACCELEROMETER_ENABLE)) && android_app->accelerometerSensor != NULL && driver.input_data) android_input_set_sensor_state(driver.input_data, 0, RETRO_SENSOR_ACCELEROMETER_DISABLE, android_app->accelerometer_event_rate); break; case APP_CMD_DESTROY: g_extern.system.shutdown = true; break; } }
static void *android_app_entry(void *data) { struct android_app* android_app = (struct android_app*)data; android_app->config = AConfiguration_new(); AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); print_cur_config(android_app); ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, NULL); android_app->looper = looper; pthread_mutex_lock(&android_app->mutex); android_app->running = 1; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); memset(&g_android, 0, sizeof(g_android)); g_android = android_app; RARCH_LOG("Native Activity started.\n"); rarch_main_clear_state(); while (!android_app->window) { if (!android_run_events(android_app)) goto exit; } rarch_init_msg_queue(); if (!android_app_start_main(android_app)) { g_settings.input.overlay[0] = 0; // threaded video doesn't work right for just displaying one frame g_settings.video.threaded = false; init_drivers(); driver.video_poke->set_aspect_ratio(driver.video_data, ASPECT_RATIO_SQUARE); rarch_render_cached_frame(); sleep(2); goto exit; } if (!g_extern.libretro_dummy) menu_rom_history_push_current(); for (;;) { if (g_extern.system.shutdown) break; else if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME)) { load_menu_game_prepare(); // If ROM load fails, we exit RetroArch. On console it might make more sense to go back to menu though ... if (load_menu_game()) g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME); else { #ifdef RARCH_CONSOLE g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU); #else return NULL; #endif } g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME); } else if (g_extern.lifecycle_mode_state & (1ULL << MODE_GAME)) { driver.input->poll(NULL); if (driver.video_poke->set_aspect_ratio) driver.video_poke->set_aspect_ratio(driver.video_data, g_settings.video.aspect_ratio_idx); if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_THROTTLE_ENABLE)) audio_start_func(); // Main loop while (rarch_main_iterate()); if (g_extern.lifecycle_mode_state & (1ULL << MODE_VIDEO_THROTTLE_ENABLE)) audio_stop_func(); g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME); } else if(g_extern.lifecycle_mode_state & (1ULL << MODE_MENU)) { g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU_PREINIT); while((input_key_pressed_func(RARCH_PAUSE_TOGGLE)) ? android_run_events(android_app) : menu_iterate()); g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU); } else break; } exit: android_app->activityState = APP_CMD_DEAD; RARCH_LOG("Deinitializing RetroArch...\n"); menu_free(); if (g_extern.config_save_on_exit && *g_extern.config_path) config_save_file(g_extern.config_path); if (g_extern.main_is_init) rarch_main_deinit(); rarch_deinit_msg_queue(); #ifdef PERF_TEST rarch_perf_log(); #endif rarch_main_clear_state(); RARCH_LOG("android_app_destroy!"); if (android_app->inputQueue != NULL) AInputQueue_detachLooper(android_app->inputQueue); AConfiguration_delete(android_app->config); // exit() here is nasty. // pthread_exit(NULL) or return NULL; causes hanging ... // Should probably called ANativeActivity_finsih(), but it's bugged, it will hang our app. exit(0); }
void StAndroidGlue::processCommand() { int8_t aCmd = -1; if(::read(myMsgRead, &aCmd, sizeof(aCmd)) == sizeof(aCmd)) { switch(aCmd) { case CommandId_SaveState: freeSavedState(); break; } } else { ST_ERROR_LOG("No data on command pipe!"); return; } // preprocessing switch(aCmd) { case CommandId_InputChanged: { pthread_mutex_lock(&myMutex); if(myInputQueue != NULL) { AInputQueue_detachLooper(myInputQueue); } myInputQueue = myInputQueuePending; if(myInputQueue != NULL) { AInputQueue_attachLooper(myInputQueue, myLooper, LooperId_INPUT, NULL, &myInputPollSource); } pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_WindowChanged: case CommandId_WindowInit: { pthread_mutex_lock(&myMutex); myWindow = myWindowPending; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_WindowTerm: { pthread_cond_broadcast(&myCond); break; } case CommandId_Resume: case CommandId_Start: case CommandId_Pause: case CommandId_Stop: { pthread_mutex_lock(&myMutex); myActivityState = aCmd; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_ConfigChanged: { AConfiguration_fromAssetManager(myConfig, myActivity->assetManager); updateMonitors(); printConfig(); break; } case CommandId_Destroy: { myToDestroy = true; break; } } signals.onAppCmd(aCmd); // post-processing switch(aCmd) { case CommandId_WindowTerm: { pthread_mutex_lock(&myMutex); myWindow = NULL; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_WindowChanged: { pthread_mutex_lock(&myMutex); myWindowPending = NULL; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_SaveState: { pthread_mutex_lock(&myMutex); myIsStateSaved = true; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); break; } case CommandId_Resume: { freeSavedState(); break; } } }
void StAndroidGlue::threadEntry() { if(myJavaVM->AttachCurrentThread(&myThJniEnv, NULL) < 0) { ST_ERROR_LOG("Failed to attach working thread to Java VM"); return; } THE_ANDROID_GLUE = this; StMessageBox::setCallback(msgBoxCallback); myConfig = AConfiguration_new(); AConfiguration_fromAssetManager(myConfig, myActivity->assetManager); updateMonitors(); printConfig(); ALooper* aLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(aLooper, myMsgRead, LooperId_MAIN, ALOOPER_EVENT_INPUT, NULL, &myCmdPollSource); myLooper = aLooper; pthread_mutex_lock(&myMutex); myIsRunning = true; pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); // try to load stereo APIs /**jclass aJClass_Real3D = myThJniEnv->FindClass("com/lge/real3d/Real3D"); if(aJClass_Real3D != NULL) { jmethodID aJMet_isStereoDisplayAvailable = myThJniEnv->GetStaticMethodID(aJClass_Real3D, "isStereoDisplayAvailable", "(Landroid/content/Contex;)Z"); postMessage("com.lge.real3d.Real3D !!!"); } jclass aJClass_HTC = myThJniEnv->FindClass("com/htc/view/DisplaySetting"); if(aJClass_HTC != NULL) { jmethodID aJMet_isStereoDisplayAvailable = myThJniEnv->GetStaticMethodID(aJClass_HTC, "setStereoscopic3DFormat", "(Landroid/view/Surface;I)Z"); postMessage("com.htc.view.DisplaySetting !!!"); } jclass aJClass_Sharp = myThJniEnv->FindClass("jp/co/sharp/android/stereo3dlcd/SurfaceController"); if(aJClass_Sharp != NULL) { jmethodID aJMet_setStereoView = myThJniEnv->GetMethodID(aJClass_Sharp, "setStereoView", "(Z)V"); postMessage("jp.co.sharp.android.stereo3dlcd !!!"); }*/ createApplication(); if(!myApp.isNull()) { if(!myApp->open()) { stError("Error: application can not be executed!"); } myApp->exec(); } else { stError("Error: no application to execute!"); } myApp.nullify(); // application is done but we are waiting for destroying event... bool isFirstWait = true; for(; !myToDestroy; ) { if(isFirstWait) { postExit(); isFirstWait = false; } StAndroidPollSource* aSource = NULL; int aNbEvents = 0; ALooper_pollAll(-1, NULL, &aNbEvents, (void** )&aSource); if(aSource != NULL) { aSource->process(this, aSource); } } freeSavedState(); pthread_mutex_lock(&myMutex); if(myInputQueue != NULL) { AInputQueue_detachLooper(myInputQueue); } AConfiguration_delete(myConfig); pthread_cond_broadcast(&myCond); pthread_mutex_unlock(&myMutex); myThJniEnv = NULL; StMessageBox::setCallback(NULL); THE_ANDROID_GLUE = NULL; myJavaVM->DetachCurrentThread(); }
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) { switch (cmd) { case APP_CMD_INPUT_CHANGED: LOGI("APP_CMD_INPUT_CHANGED\n"); pthread_mutex_lock(&android_app->mutex); if (android_app->inputQueue != NULL) { AInputQueue_detachLooper(android_app->inputQueue); } android_app->inputQueue = android_app->pendingInputQueue; if (android_app->inputQueue != NULL) { LOGI("Attaching input queue to looper"); AInputQueue_attachLooper(android_app->inputQueue, android_app->looper, LOOPER_ID_INPUT, NULL, &android_app->inputPollSource); } pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_INIT_WINDOW: LOGI("APP_CMD_INIT_WINDOW\n"); pthread_mutex_lock(&android_app->mutex); android_app->window = android_app->pendingWindow; if (android_app->window && ANativeWindow_getWidth(android_app->window) && ANativeWindow_getHeight(android_app->window)) { android_app->lifecycleFlags |= NV_APP_STATUS_HAS_REAL_SURFACE; } else { android_app->lifecycleFlags &= ~NV_APP_STATUS_HAS_REAL_SURFACE; } pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_TERM_WINDOW: LOGI("APP_CMD_TERM_WINDOW\n"); android_app->lifecycleFlags &= ~NV_APP_STATUS_HAS_REAL_SURFACE; pthread_cond_broadcast(&android_app->cond); break; case APP_CMD_WINDOW_RESIZED: LOGI("APP_CMD_WINDOW_RESIZED\n"); pthread_mutex_lock(&android_app->mutex); if (android_app->window && ANativeWindow_getWidth(android_app->window) && ANativeWindow_getHeight(android_app->window)) { android_app->lifecycleFlags |= NV_APP_STATUS_HAS_REAL_SURFACE; } else { android_app->lifecycleFlags &= ~NV_APP_STATUS_HAS_REAL_SURFACE; } pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_GAINED_FOCUS: LOGI("APP_CMD_GAINED_FOCUS\n"); pthread_mutex_lock(&android_app->mutex); android_app->lifecycleFlags |= NV_APP_STATUS_FOCUSED; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_LOST_FOCUS: LOGI("APP_CMD_LOST_FOCUS\n"); pthread_mutex_lock(&android_app->mutex); android_app->lifecycleFlags &= ~NV_APP_STATUS_FOCUSED; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_RESUME: LOGI("activityState=%d\n", cmd); pthread_mutex_lock(&android_app->mutex); android_app->lifecycleFlags |= NV_APP_STATUS_ACTIVE; android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_START: LOGI("activityState=%d\n", cmd); pthread_mutex_lock(&android_app->mutex); android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_PAUSE: LOGI("activityState=%d\n", cmd); pthread_mutex_lock(&android_app->mutex); android_app->lifecycleFlags &= ~NV_APP_STATUS_ACTIVE; android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_STOP: LOGI("activityState=%d\n", cmd); pthread_mutex_lock(&android_app->mutex); android_app->activityState = cmd; pthread_cond_broadcast(&android_app->cond); pthread_mutex_unlock(&android_app->mutex); break; case APP_CMD_CONFIG_CHANGED: LOGI("APP_CMD_CONFIG_CHANGED\n"); AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager); print_cur_config(android_app); break; case APP_CMD_DESTROY: LOGI("APP_CMD_DESTROY\n"); android_app->lifecycleFlags &= ~NV_APP_STATUS_RUNNING; break; } }