static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) { pthread_mutex_lock(&android_app->mutex); if (android_app->pendingWindow != NULL) { android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); } android_app->pendingWindow = window; if (window != NULL) { android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); } while (android_app->window != android_app->pendingWindow) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } pthread_mutex_unlock(&android_app->mutex); }
static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) { pthread_mutex_lock(&android_app->mutex); android_app_write_cmd(android_app, cmd); while (android_app->activityState != cmd) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } pthread_mutex_unlock(&android_app->mutex); }
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) { pthread_mutex_lock(&android_app->mutex); android_app->pendingInputQueue = inputQueue; android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); while (android_app->inputQueue != android_app->pendingInputQueue) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } pthread_mutex_unlock(&android_app->mutex); }
static void onConfigurationChanged (ANativeActivity *activity) { struct android_app* android_app = (struct android_app*)activity->instance; if (!android_app) return; RARCH_LOG("ConfigurationChanged: %p\n", activity); android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); }
void wake_animation( void ) { if( engine.have_focus ) { if( !engine.state.animating ) { engine.state.animating = 1; android_app_write_cmd( engine.app, APP_CMD_WAKE); } } }
static void android_app_set_window (void *data, ANativeWindow* window) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; slock_lock(android_app->mutex); if (android_app->pendingWindow) android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW); android_app->pendingWindow = window; if (window) android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW); while (android_app->window != android_app->pendingWindow) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); }
static void android_app_set_activity_state (void *data, int8_t cmd) { struct android_app *android_app = (struct android_app*)data; pthread_mutex_lock(&android_app->mutex); android_app_write_cmd(android_app, cmd); while (android_app->activityState != cmd && android_app->activityState != APP_CMD_DEAD) pthread_cond_wait(&android_app->cond, &android_app->mutex); pthread_mutex_unlock(&android_app->mutex); if (android_app->activityState == APP_CMD_DEAD) RARCH_LOG("RetroArch thread is dead.\n"); }
static void android_app_set_input (void *data, AInputQueue* inputQueue) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; slock_lock(android_app->mutex); android_app->pendingInputQueue = inputQueue; android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED); while (android_app->inputQueue != android_app->pendingInputQueue) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); }
static void android_app_free(struct android_app* android_app) { pthread_mutex_lock(&android_app->mutex); android_app_write_cmd(android_app, APP_CMD_DESTROY); while (!android_app->destroyed) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } pthread_mutex_unlock(&android_app->mutex); close(android_app->msgread); close(android_app->msgwrite); pthread_cond_destroy(&android_app->cond); pthread_mutex_destroy(&android_app->mutex); free(android_app); }
static void android_app_set_activity_state (void *data, int8_t cmd) { struct android_app *android_app = (struct android_app*)data; if (!android_app) return; slock_lock(android_app->mutex); android_app_write_cmd(android_app, cmd); while (android_app->activityState != cmd && android_app->activityState != APP_CMD_DEAD) scond_wait(android_app->cond, android_app->mutex); slock_unlock(android_app->mutex); if (android_app->activityState == APP_CMD_DEAD) RARCH_LOG("RetroArch native thread is dead.\n"); }
static void android_app_free(struct android_app* android_app) { pthread_mutex_lock(&android_app->mutex); android_app_write_cmd(android_app, APP_CMD_DESTROY); while (!android_app->destroyed) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } pthread_mutex_unlock(&android_app->mutex); (*android_app->activity->env)->DeleteGlobalRef(android_app->activity->env, android_app->appThreadThis); (*android_app->activity->env)->DeleteGlobalRef(android_app->activity->env, android_app->appThreadDisp); close(android_app->msgread); close(android_app->msgwrite); pthread_cond_destroy(&android_app->cond); pthread_mutex_destroy(&android_app->mutex); free(android_app); }
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) { struct android_app* android_app = (struct android_app*)activity->instance; void* savedState = NULL; pthread_mutex_lock(&android_app->mutex); android_app->stateSaved = 0; android_app_write_cmd(android_app, APP_CMD_SAVE_STATE); while (!android_app->stateSaved) { pthread_cond_wait(&android_app->cond, &android_app->mutex); } if (android_app->savedState != NULL) { savedState = android_app->savedState; *outLen = android_app->savedStateSize; android_app->savedState = NULL; android_app->savedStateSize = 0; } pthread_mutex_unlock(&android_app->mutex); return savedState; }
static void onWindowFocusChanged(ANativeActivity* activity, int focused) { LOGV("WindowFocusChanged: %p -- %d\n", activity, focused); android_app_write_cmd((struct android_app*)activity->instance, focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS); }
static void onLowMemory(ANativeActivity* activity) { struct android_app* android_app = (struct android_app*)activity->instance; LOGV("LowMemory: %p\n", activity); android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY); }
static void onConfigurationChanged(ANativeActivity* activity) { struct android_app* android_app = (struct android_app*)activity->instance; LOGI("ConfigurationChanged: %p\n", (void*)activity); android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED); }
static void nv_app_resize_window(struct android_app* android_app, ANativeWindow* window) { android_app_write_cmd(android_app, APP_CMD_WINDOW_RESIZED); }
void* BeginNormalProcess( void*param ) { engine.wait_for_startup = 0; sched_yield(); LOGI( "BeginNormalProcess: %d %d %d %d %p %p", engine.state.restarting, engine.state.closed, engine.state.opened, engine.wait_for_startup, myname, BeginNormalProcess ); while( !engine.data_path ) sched_yield(); if( !engine.state.restarting && !myname ) { if( findself() ) { do { char buf[256]; void (*InvokeDeadstart)(void ); void (*MarkRootDeadstartComplete)(void ); const char * filepath = engine.data_path;//malloc( 256 ); //snprintf( filepath, 256, "/data/data/%s/files", engine.data_path ); LOGI( "my path [%s][%s][%s]", filepath, mypath, myname ); if( chdir( filepath ) ) //if( chdir( "../files" ) ) { LOGI( "path change failed to [%s]", mypath ); if( mkdir( filepath /*"../files"*/, 0700 ) ) { LOGI( "path change failed to [%s]", mypath ); } chdir( filepath ); } getcwd( buf, 256 ); LOGI( "ended up in directory:%s", buf ); { FILE *assets_saved = fopen( "assets.exported", "rb" ); if( !assets_saved ) { ExportAssets(); assets_saved = fopen( "assets.exported", "wb" ); } fclose( assets_saved ); } // do not auto load libraries #ifndef BUILD_PORTABLE_EXECUTABLE LoadLibrary( mypath, "libbag.externals.so" ); { void *lib; void (*RunExits)(void ); lib = LoadLibrary( mypath, "libbag.so" ); RunExits = dlsym( lib, "RunExits" ); if( RunExits ) atexit( RunExits ); else LOGI( "Failed to get symbol RunExits:%s", dlerror() ); InvokeDeadstart = dlsym( lib, "InvokeDeadstart" ); if( !InvokeDeadstart ) LOGI( "Failed to get InvokeDeadstart entry" ); MarkRootDeadstartComplete = dlsym( lib, "MarkRootDeadstartComplete" ); if( !MarkRootDeadstartComplete ) LOGI( "Failed to get MarkRootDeadstartComplete entry" ); { void (*f)(char*); f = dlsym( lib, "SACKSystemSetProgramPath" ); f( mypath ); f = dlsym( lib, "SACKSystemSetProgramName" ); f( myname ); f = dlsym( lib, "SACKSystemSetWorkingPath" ); f( buf ); } } LoadLibrary( mypath, "libbag.psi.so" ); #endif { void *lib; snprintf( buf, 256, "%s.code.so", myname ); //LOGI( "Load library... %s", buf ); lib = LoadLibrary( mypath, buf ); // assume we need to init this; it's probably a portable target if( !InvokeDeadstart ) { // this normally comes from bag; but a static/portable application may have it linked as part of its code InvokeDeadstart = dlsym( lib, "InvokeDeadstart" ); { void (*f)(char*); f = dlsym( lib, "SACKSystemSetProgramPath" ); f( mypath ); f = dlsym( lib, "SACKSystemSetProgramName" ); f( myname ); f = dlsym( lib, "SACKSystemSetWorkingPath" ); f( buf ); } MarkRootDeadstartComplete = dlsym( lib, "MarkRootDeadstartComplete" ); } VideoPlayer_PlayMedia = dlsym( lib, "VideoPlayer_PlayMedia" ); SACK_Main = dlsym( lib, "SACK_Main" ); if( !SACK_Main ) { // allow normal main fail processing break; } //LOGI( "Invoke Deadstart..." ); InvokeDeadstart(); //LOGI( "Deadstart Completed..." ); MarkRootDeadstartComplete(); // somehow these will be loaded // but we don't know where, but it's pretty safe to assume the names are unique, or // first-come-first-serve is appropriate BagVidlibPureglSetNativeWindowHandle = (void (*)(NativeWindowType ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SetNativeWindowHandle" ); if( !BagVidlibPureglSetNativeWindowHandle ) LOGI( "Failed to get SetNativeWindowHandle:%s", dlerror() ); BagVidlibPureglSetKeyboardMetric = (void (*)(int ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SetKeyboardMetric" ); BagVidlibPureglFirstRender = (void (*)(void ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_DoFirstRender" ); //if( !BagVidlibPureglFirstRender ) // LOGI( "Failed to get BagVidlibPureglFirstRender:%s", dlerror() ); BagVidlibPureglRenderPass = (int (*)(void ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_DoRenderPass" ); //if( !BagVidlibPureglRenderPass ) // LOGI( "Failed to get DoRenderPass:%s", dlerror() ); BagVidlibPureglOpenCameras = (void (*)(void ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_OpenCameras" ); if( !BagVidlibPureglOpenCameras ) LOGI( "Failed to get OpenCameras:%s", dlerror() ); BagVidlibPureglSendKeyEvents = (int(*)(int,int,int))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SendKeyEvents" ); BagVidlibPureglSendTouchEvents = (void (*)(int,PINPUT_POINT ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SendTouchEvents" ); BagVidlibPureglCloseDisplay = (void(*)(void))dlsym( RTLD_DEFAULT, "SACK_Vidlib_CloseDisplay" ); BagVidlibPureglSurfaceLost = (void(*)(void))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SurfaceLost" ); // egl event BagVidlibPureglSurfaceGained = (void(*)(NativeWindowType))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SurfaceGained" ); // egl event BagVidlibPureglPauseDisplay = (void(*)(void))dlsym( RTLD_DEFAULT,"SACK_Vidlib_PauseDisplay" ); BagVidlibPureglResumeDisplay = (void(*)(void))dlsym( RTLD_DEFAULT,"SACK_Vidlib_ResumeDisplay" ); BagVidlibPureglSetTriggerKeyboard = (void(*)(void(*)(void),void(*)(void),int(*get_status_metric)(void) ,int(*get_keyboard_metric)(void) ,char*(*get_key_text)(void) ))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SetTriggerKeyboard" ); if( BagVidlibPureglSetTriggerKeyboard ) BagVidlibPureglSetTriggerKeyboard( show_keyboard, hide_keyboard, AndroidGetStatusMetric, AndroidGetKeyboardMetric, AndroidGetCurrentKeyText ); BagVidlibPureglSetAnimationWake = (void(*)(void(*)(void)))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SetAnimationWake" ); if( BagVidlibPureglSetAnimationWake ) BagVidlibPureglSetAnimationWake( wake_animation ); BagVidlibPureglSetSleepSuspend = (void(*)(void(*)(int)))dlsym( RTLD_DEFAULT, "SACK_Vidlib_SetSleepSuspend" ); if( BagVidlibPureglSetSleepSuspend ) BagVidlibPureglSetSleepSuspend( SuspendSleep ); // shouldn't need this shortly; was more about doing things my way than the android way //engine.wait_for_display_init = 1; engine.wait_for_startup = 0; // resume other threads so potentially the display is the next thing initialized. //while( engine.wait_for_display_init ) sched_yield(); //break; } } while( 0 ); } else if( !myname ) { LOGI( "Failed to open procself" ); myname = "Reading /proc/self/maps failed"; } } else engine.wait_for_startup = 0; if( !SACK_Main ) { LOGI( "(still)Failed to get SACK_Main entry point; I am [%s]", myname ); return 0; } LOGI( "Start Application..." ); if( engine.app->pendingWindow && BagVidlibPureglSetNativeWindowHandle ) BagVidlibPureglSetNativeWindowHandle( engine.app->pendingWindow ); if( engine.resumed ) { if( BagVidlibPureglResumeDisplay ) BagVidlibPureglResumeDisplay(); engine.state.animating = 1; android_app_write_cmd( engine.app, APP_CMD_WAKE); } SACK_Main( 0, NULL ); engine.state.closed = 1; LOGI( "Main exited... and so should we all..." ); return NULL; }