Path: blob/main_old/util/android/third_party/android_native_app_glue.c
1694 views
/*1* Copyright (C) 2010 The Android Open Source Project2*3* Licensed under the Apache License, Version 2.0 (the "License");4* you may not use this file except in compliance with the License.5* You may obtain a copy of the License at6*7* http://www.apache.org/licenses/LICENSE-2.08*9* Unless required by applicable law or agreed to in writing, software10* distributed under the License is distributed on an "AS IS" BASIS,11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12* See the License for the specific language governing permissions and13* limitations under the License.14*15*/1617#include <jni.h>1819#include <errno.h>20#include <stdlib.h>21#include <string.h>22#include <unistd.h>23#include <sys/resource.h>2425#include "android_native_app_glue.h"26#include <android/log.h>2728#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))29#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))3031/* For debug builds, always enable the debug traces in this library */32#ifndef NDEBUG33# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))34#else35# define LOGV(...) ((void)0)36#endif3738static void free_saved_state(struct android_app* android_app) {39pthread_mutex_lock(&android_app->mutex);40if (android_app->savedState != NULL) {41free(android_app->savedState);42android_app->savedState = NULL;43android_app->savedStateSize = 0;44}45pthread_mutex_unlock(&android_app->mutex);46}4748int8_t android_app_read_cmd(struct android_app* android_app) {49int8_t cmd;50if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {51switch (cmd) {52case APP_CMD_SAVE_STATE:53free_saved_state(android_app);54break;55}56return cmd;57} else {58LOGE("No data on command pipe!");59}60return -1;61}6263static void print_cur_config(struct android_app* android_app) {64char lang[2], country[2];65AConfiguration_getLanguage(android_app->config, lang);66AConfiguration_getCountry(android_app->config, country);6768LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "69"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "70"modetype=%d modenight=%d",71AConfiguration_getMcc(android_app->config),72AConfiguration_getMnc(android_app->config),73lang[0], lang[1], country[0], country[1],74AConfiguration_getOrientation(android_app->config),75AConfiguration_getTouchscreen(android_app->config),76AConfiguration_getDensity(android_app->config),77AConfiguration_getKeyboard(android_app->config),78AConfiguration_getNavigation(android_app->config),79AConfiguration_getKeysHidden(android_app->config),80AConfiguration_getNavHidden(android_app->config),81AConfiguration_getSdkVersion(android_app->config),82AConfiguration_getScreenSize(android_app->config),83AConfiguration_getScreenLong(android_app->config),84AConfiguration_getUiModeType(android_app->config),85AConfiguration_getUiModeNight(android_app->config));86}8788void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {89switch (cmd) {90case APP_CMD_INPUT_CHANGED:91LOGV("APP_CMD_INPUT_CHANGED\n");92pthread_mutex_lock(&android_app->mutex);93if (android_app->inputQueue != NULL) {94AInputQueue_detachLooper(android_app->inputQueue);95}96android_app->inputQueue = android_app->pendingInputQueue;97if (android_app->inputQueue != NULL) {98LOGV("Attaching input queue to looper");99AInputQueue_attachLooper(android_app->inputQueue,100android_app->looper, LOOPER_ID_INPUT, NULL,101&android_app->inputPollSource);102}103pthread_cond_broadcast(&android_app->cond);104pthread_mutex_unlock(&android_app->mutex);105break;106107case APP_CMD_INIT_WINDOW:108LOGV("APP_CMD_INIT_WINDOW\n");109pthread_mutex_lock(&android_app->mutex);110android_app->window = android_app->pendingWindow;111pthread_cond_broadcast(&android_app->cond);112pthread_mutex_unlock(&android_app->mutex);113break;114115case APP_CMD_TERM_WINDOW:116LOGV("APP_CMD_TERM_WINDOW\n");117pthread_cond_broadcast(&android_app->cond);118break;119120case APP_CMD_RESUME:121case APP_CMD_START:122case APP_CMD_PAUSE:123case APP_CMD_STOP:124LOGV("activityState=%d\n", cmd);125pthread_mutex_lock(&android_app->mutex);126android_app->activityState = cmd;127pthread_cond_broadcast(&android_app->cond);128pthread_mutex_unlock(&android_app->mutex);129break;130131case APP_CMD_CONFIG_CHANGED:132LOGV("APP_CMD_CONFIG_CHANGED\n");133AConfiguration_fromAssetManager(android_app->config,134android_app->activity->assetManager);135print_cur_config(android_app);136break;137138case APP_CMD_DESTROY:139LOGV("APP_CMD_DESTROY\n");140android_app->destroyRequested = 1;141break;142}143}144145void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {146switch (cmd) {147case APP_CMD_TERM_WINDOW:148LOGV("APP_CMD_TERM_WINDOW\n");149pthread_mutex_lock(&android_app->mutex);150android_app->window = NULL;151pthread_cond_broadcast(&android_app->cond);152pthread_mutex_unlock(&android_app->mutex);153break;154155case APP_CMD_SAVE_STATE:156LOGV("APP_CMD_SAVE_STATE\n");157pthread_mutex_lock(&android_app->mutex);158android_app->stateSaved = 1;159pthread_cond_broadcast(&android_app->cond);160pthread_mutex_unlock(&android_app->mutex);161break;162163case APP_CMD_RESUME:164free_saved_state(android_app);165break;166}167}168169void app_dummy(void) {170171}172173static void android_app_destroy(struct android_app* android_app) {174LOGV("android_app_destroy!");175free_saved_state(android_app);176pthread_mutex_lock(&android_app->mutex);177if (android_app->inputQueue != NULL) {178AInputQueue_detachLooper(android_app->inputQueue);179}180AConfiguration_delete(android_app->config);181android_app->destroyed = 1;182pthread_cond_broadcast(&android_app->cond);183pthread_mutex_unlock(&android_app->mutex);184// Can't touch android_app object after this.185}186187static void process_input(struct android_app* app, struct android_poll_source* source) {188AInputEvent* event = NULL;189while (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {190LOGV("New input event: type=%d\n", AInputEvent_getType(event));191if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {192continue;193}194int32_t handled = 0;195if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);196AInputQueue_finishEvent(app->inputQueue, event, handled);197}198}199200static void process_cmd(struct android_app* app, struct android_poll_source* source) {201int8_t cmd = android_app_read_cmd(app);202android_app_pre_exec_cmd(app, cmd);203if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);204android_app_post_exec_cmd(app, cmd);205}206207static void* android_app_entry(void* param) {208struct android_app* android_app = (struct android_app*)param;209210android_app->config = AConfiguration_new();211AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);212213print_cur_config(android_app);214215android_app->cmdPollSource.id = LOOPER_ID_MAIN;216android_app->cmdPollSource.app = android_app;217android_app->cmdPollSource.process = process_cmd;218android_app->inputPollSource.id = LOOPER_ID_INPUT;219android_app->inputPollSource.app = android_app;220android_app->inputPollSource.process = process_input;221222ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);223ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,224&android_app->cmdPollSource);225android_app->looper = looper;226227pthread_mutex_lock(&android_app->mutex);228android_app->running = 1;229pthread_cond_broadcast(&android_app->cond);230pthread_mutex_unlock(&android_app->mutex);231232android_main(android_app);233234android_app_destroy(android_app);235return NULL;236}237238// --------------------------------------------------------------------239// Native activity interaction (called from main thread)240// --------------------------------------------------------------------241242static struct android_app* android_app_create(ANativeActivity* activity,243void* savedState, size_t savedStateSize) {244struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));245memset(android_app, 0, sizeof(struct android_app));246android_app->activity = activity;247248pthread_mutex_init(&android_app->mutex, NULL);249pthread_cond_init(&android_app->cond, NULL);250251if (savedState != NULL) {252android_app->savedState = malloc(savedStateSize);253android_app->savedStateSize = savedStateSize;254memcpy(android_app->savedState, savedState, savedStateSize);255}256257int msgpipe[2];258if (pipe(msgpipe)) {259LOGE("could not create pipe: %s", strerror(errno));260return NULL;261}262android_app->msgread = msgpipe[0];263android_app->msgwrite = msgpipe[1];264265pthread_attr_t attr;266pthread_attr_init(&attr);267pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);268pthread_create(&android_app->thread, &attr, android_app_entry, android_app);269270// Wait for thread to start.271pthread_mutex_lock(&android_app->mutex);272while (!android_app->running) {273pthread_cond_wait(&android_app->cond, &android_app->mutex);274}275pthread_mutex_unlock(&android_app->mutex);276277return android_app;278}279280static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {281if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {282LOGE("Failure writing android_app cmd: %s\n", strerror(errno));283}284}285286static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {287pthread_mutex_lock(&android_app->mutex);288android_app->pendingInputQueue = inputQueue;289android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);290while (android_app->inputQueue != android_app->pendingInputQueue) {291pthread_cond_wait(&android_app->cond, &android_app->mutex);292}293pthread_mutex_unlock(&android_app->mutex);294}295296static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {297pthread_mutex_lock(&android_app->mutex);298if (android_app->pendingWindow != NULL) {299android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);300}301android_app->pendingWindow = window;302if (window != NULL) {303android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);304}305while (android_app->window != android_app->pendingWindow) {306pthread_cond_wait(&android_app->cond, &android_app->mutex);307}308pthread_mutex_unlock(&android_app->mutex);309}310311static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {312pthread_mutex_lock(&android_app->mutex);313android_app_write_cmd(android_app, cmd);314while (android_app->activityState != cmd) {315pthread_cond_wait(&android_app->cond, &android_app->mutex);316}317pthread_mutex_unlock(&android_app->mutex);318}319320static void android_app_free(struct android_app* android_app) {321pthread_mutex_lock(&android_app->mutex);322android_app_write_cmd(android_app, APP_CMD_DESTROY);323while (!android_app->destroyed) {324pthread_cond_wait(&android_app->cond, &android_app->mutex);325}326pthread_mutex_unlock(&android_app->mutex);327328close(android_app->msgread);329close(android_app->msgwrite);330pthread_cond_destroy(&android_app->cond);331pthread_mutex_destroy(&android_app->mutex);332free(android_app);333}334335static void onDestroy(ANativeActivity* activity) {336LOGV("Destroy: %p\n", activity);337android_app_free((struct android_app*)activity->instance);338}339340static void onStart(ANativeActivity* activity) {341LOGV("Start: %p\n", activity);342android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);343}344345static void onResume(ANativeActivity* activity) {346LOGV("Resume: %p\n", activity);347android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);348}349350static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {351struct android_app* android_app = (struct android_app*)activity->instance;352void* savedState = NULL;353354LOGV("SaveInstanceState: %p\n", activity);355pthread_mutex_lock(&android_app->mutex);356android_app->stateSaved = 0;357android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);358while (!android_app->stateSaved) {359pthread_cond_wait(&android_app->cond, &android_app->mutex);360}361362if (android_app->savedState != NULL) {363savedState = android_app->savedState;364*outLen = android_app->savedStateSize;365android_app->savedState = NULL;366android_app->savedStateSize = 0;367}368369pthread_mutex_unlock(&android_app->mutex);370371return savedState;372}373374static void onPause(ANativeActivity* activity) {375LOGV("Pause: %p\n", activity);376android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);377}378379static void onStop(ANativeActivity* activity) {380LOGV("Stop: %p\n", activity);381android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);382}383384static void onConfigurationChanged(ANativeActivity* activity) {385struct android_app* android_app = (struct android_app*)activity->instance;386LOGV("ConfigurationChanged: %p\n", activity);387android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);388}389390static void onLowMemory(ANativeActivity* activity) {391struct android_app* android_app = (struct android_app*)activity->instance;392LOGV("LowMemory: %p\n", activity);393android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);394}395396static void onWindowFocusChanged(ANativeActivity* activity, int focused) {397LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);398android_app_write_cmd((struct android_app*)activity->instance,399focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);400}401402static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {403LOGV("NativeWindowCreated: %p -- %p\n", activity, window);404android_app_set_window((struct android_app*)activity->instance, window);405}406407static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {408LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);409android_app_set_window((struct android_app*)activity->instance, NULL);410}411412static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {413LOGV("InputQueueCreated: %p -- %p\n", activity, queue);414android_app_set_input((struct android_app*)activity->instance, queue);415}416417static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {418LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);419android_app_set_input((struct android_app*)activity->instance, NULL);420}421422__attribute__((visibility("default"))) void ANativeActivity_onCreate(ANativeActivity* activity,423void* savedState, size_t savedStateSize) {424LOGV("Creating: %p\n", activity);425activity->callbacks->onDestroy = onDestroy;426activity->callbacks->onStart = onStart;427activity->callbacks->onResume = onResume;428activity->callbacks->onSaveInstanceState = onSaveInstanceState;429activity->callbacks->onPause = onPause;430activity->callbacks->onStop = onStop;431activity->callbacks->onConfigurationChanged = onConfigurationChanged;432activity->callbacks->onLowMemory = onLowMemory;433activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;434activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;435activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;436activity->callbacks->onInputQueueCreated = onInputQueueCreated;437activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;438439activity->instance = android_app_create(activity, savedState, savedStateSize);440}441442443