Remove prebuilt static library "libthreaded_app.a".
Make the "glue library" part of the NDK as an importable module,
this has several benefits:
- no need to distribute a binary here with no easy way to regenerate it
- no need to explicitely list -lthreaded_app in your LOCAL_LDLIBS
(this is handled automatically by the module import capability)
- allows easier native debugging of what's really happening.
Note that the header is renamed <threaded_native_app.h>
+ Modify the native-activity sample to use and import the new module
+ Start documenting usage in the header file. We probably need something
better, and will probably put it under development/ndk/docs/ at some
point.
After this patch, we should be able to get rid of the code under
framework/base/native/{include.glue}
Change-Id: I6e81d70a225a6ca006beabf6e8b42529e8f371b9
This commit is contained in:
Binary file not shown.
@@ -18,6 +18,9 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := native-activity
|
||||
LOCAL_SRC_FILES := main.c glutils.c
|
||||
LOCAL_LDLIBS := -lthreaded_app -llog -landroid -lEGL -lGLESv1_CM
|
||||
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv1_CM
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,android/native_app_glue)
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <android_glue/threaded_app.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include "glutils.h"
|
||||
|
||||
struct engine {
|
||||
struct android_app* app;
|
||||
|
||||
|
||||
int animating;
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
@@ -69,13 +69,13 @@ static int engine_init_display(struct engine* engine) {
|
||||
engine->width = w;
|
||||
engine->height = h;
|
||||
engine->angle = 0;
|
||||
|
||||
|
||||
// Initialize GL state.
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ static void engine_draw_frame(struct engine* engine) {
|
||||
// No display.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
glClearColor(((float)engine->x)/engine->width, engine->angle,
|
||||
((float)engine->y)/engine->height, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
@@ -108,7 +108,7 @@ static void engine_draw_frame(struct engine* engine) {
|
||||
#endif
|
||||
|
||||
eglSwapBuffers(engine->display, engine->surface);
|
||||
|
||||
|
||||
//engine->angle += 1.2f;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ static int engine_do_ui_event(struct engine* engine) {
|
||||
} else {
|
||||
LOGI("Failure reading next input event: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -169,19 +169,19 @@ static int32_t engine_do_main_cmd(struct engine* engine) {
|
||||
res = android_app_exec_cmd(engine->app, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void android_main(struct android_app* state) {
|
||||
struct engine engine;
|
||||
|
||||
|
||||
memset(&engine, 0, sizeof(engine));
|
||||
state->userData = &engine;
|
||||
engine.app = state;
|
||||
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
|
||||
|
||||
while (1) {
|
||||
// Read all pending events.
|
||||
int fd;
|
||||
@@ -201,7 +201,7 @@ void android_main(struct android_app* state) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (engine.animating) {
|
||||
// Done with events; draw next animation frame.
|
||||
engine.angle += .01f;
|
||||
|
||||
@@ -18,6 +18,9 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := native-plasma
|
||||
LOCAL_SRC_FILES := plasma.c
|
||||
LOCAL_LDLIBS := -lthreaded_app -lm -llog -landroid
|
||||
LOCAL_LDLIBS := -lm -llog -landroid
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
$(call import-module,android/native_app_glue)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <android_glue/threaded_app.h>
|
||||
#include <android_native_app_glue.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <jni.h>
|
||||
@@ -374,9 +374,9 @@ stats_endFrame( Stats* s )
|
||||
|
||||
struct engine {
|
||||
struct android_app* app;
|
||||
|
||||
|
||||
Stats stats;
|
||||
|
||||
|
||||
int animating;
|
||||
};
|
||||
|
||||
@@ -385,20 +385,20 @@ static void engine_draw_frame(struct engine* engine) {
|
||||
// No window.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ANativeWindow_Buffer buffer;
|
||||
if (ANativeWindow_lock(engine->app->window, &buffer, NULL) < 0) {
|
||||
LOGW("Unable to lock window buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
stats_startFrame(&engine->stats);
|
||||
|
||||
struct timespec t;
|
||||
t.tv_sec = t.tv_nsec = 0;
|
||||
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||
int64_t time_ms = (((int64_t)t.tv_sec)*1000000000LL + t.tv_nsec)/1000000;
|
||||
|
||||
|
||||
/* Now fill the values with a nice little plasma */
|
||||
fill_plasma(&buffer, time_ms);
|
||||
|
||||
@@ -429,7 +429,7 @@ static int engine_do_ui_event(struct engine* engine) {
|
||||
} else {
|
||||
LOGI("Failure reading next input event: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -453,7 +453,7 @@ static int32_t engine_do_main_cmd(struct engine* engine) {
|
||||
res = android_app_exec_cmd(engine->app, cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -461,20 +461,20 @@ void android_main(struct android_app* state) {
|
||||
static int init;
|
||||
|
||||
struct engine engine;
|
||||
|
||||
|
||||
memset(&engine, 0, sizeof(engine));
|
||||
state->userData = &engine;
|
||||
engine.app = state;
|
||||
|
||||
|
||||
if (!init) {
|
||||
init_tables();
|
||||
init = 1;
|
||||
}
|
||||
|
||||
|
||||
stats_init(&engine.stats);
|
||||
|
||||
|
||||
// loop waiting for stuff to do.
|
||||
|
||||
|
||||
while (1) {
|
||||
// Read all pending events.
|
||||
int fd;
|
||||
@@ -494,7 +494,7 @@ void android_main(struct android_app* state) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (engine.animating) {
|
||||
engine_draw_frame(&engine);
|
||||
}
|
||||
|
||||
10
ndk/sources/android/native_app_glue/Android.mk
Normal file
10
ndk/sources/android/native_app_glue/Android.mk
Normal file
@@ -0,0 +1,10 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= android_native_app_glue
|
||||
LOCAL_SRC_FILES:= android_native_app_glue.c
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
|
||||
LOCAL_EXPORT_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
278
ndk/sources/android/native_app_glue/android_native_app_glue.c
Normal file
278
ndk/sources/android/native_app_glue/android_native_app_glue.c
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "android_native_app_glue.h"
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
|
||||
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "threaded_app", __VA_ARGS__))
|
||||
|
||||
int8_t android_app_read_cmd(struct android_app* android_app) {
|
||||
int8_t cmd;
|
||||
if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
|
||||
return cmd;
|
||||
} else {
|
||||
LOGW("No data on command pipe!");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t android_app_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, NULL, (void*)LOOPER_ID_EVENT);
|
||||
}
|
||||
pthread_cond_broadcast(&android_app->cond);
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
break;
|
||||
|
||||
case APP_CMD_WINDOW_CHANGED:
|
||||
LOGI("APP_CMD_WINDOW_CHANGED\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_START:
|
||||
case APP_CMD_RESUME:
|
||||
case APP_CMD_PAUSE:
|
||||
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_DESTROY:
|
||||
LOGI("APP_CMD_DESTROY\n");
|
||||
android_app->destroyRequested = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return android_app->destroyRequested ? 0 : 1;
|
||||
}
|
||||
|
||||
static void android_app_destroy(struct android_app* android_app) {
|
||||
LOGI("android_app_destroy!");
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
if (android_app->inputQueue != NULL) {
|
||||
AInputQueue_detachLooper(android_app->inputQueue);
|
||||
}
|
||||
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* android_app_entry(void* param) {
|
||||
struct android_app* android_app = (struct android_app*)param;
|
||||
|
||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||
ALooper_addFd(looper, android_app->msgread, POLLIN, NULL, (void*)LOOPER_ID_MAIN);
|
||||
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);
|
||||
|
||||
android_main(android_app);
|
||||
|
||||
android_app_destroy(android_app);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// Native activity interaction (called from main thread)
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
static struct android_app* android_app_create(ANativeActivity* activity) {
|
||||
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
|
||||
memset(android_app, 0, sizeof(struct android_app));
|
||||
android_app->activity = activity;
|
||||
|
||||
pthread_mutex_init(&android_app->mutex, NULL);
|
||||
pthread_cond_init(&android_app->cond, NULL);
|
||||
|
||||
int msgpipe[2];
|
||||
if (pipe(msgpipe)) {
|
||||
LOGI("could not create pipe: %s", strerror(errno));
|
||||
}
|
||||
android_app->msgread = msgpipe[0];
|
||||
android_app->msgwrite = msgpipe[1];
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
|
||||
|
||||
// Wait for thread to start.
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
while (!android_app->running) {
|
||||
pthread_cond_wait(&android_app->cond, &android_app->mutex);
|
||||
}
|
||||
pthread_mutex_unlock(&android_app->mutex);
|
||||
|
||||
return android_app;
|
||||
}
|
||||
|
||||
static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
|
||||
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
|
||||
LOGI("Failure writing android_app cmd: %s\n", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
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 android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
android_app->pendingWindow = window;
|
||||
android_app_write_cmd(android_app, APP_CMD_WINDOW_CHANGED);
|
||||
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_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 onDestroy(ANativeActivity* activity) {
|
||||
LOGI("Destroy: %p\n", activity);
|
||||
android_app_free((struct android_app*)activity->instance);
|
||||
}
|
||||
|
||||
static void onStart(ANativeActivity* activity) {
|
||||
LOGI("Start: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
|
||||
}
|
||||
|
||||
static void onResume(ANativeActivity* activity) {
|
||||
LOGI("Resume: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
|
||||
}
|
||||
|
||||
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
|
||||
LOGI("SaveInstanceState: %p\n", activity);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void onPause(ANativeActivity* activity) {
|
||||
LOGI("Pause: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
|
||||
}
|
||||
|
||||
static void onStop(ANativeActivity* activity) {
|
||||
LOGI("Stop: %p\n", activity);
|
||||
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
|
||||
}
|
||||
|
||||
static void onLowMemory(ANativeActivity* activity) {
|
||||
LOGI("LowMemory: %p\n", activity);
|
||||
}
|
||||
|
||||
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
|
||||
LOGI("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 onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGI("NativeWindowCreated: %p -- %p\n", activity, window);
|
||||
android_app_set_window((struct android_app*)activity->instance, window);
|
||||
}
|
||||
|
||||
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
|
||||
LOGI("NativeWindowDestroyed: %p -- %p\n", activity, window);
|
||||
android_app_set_window((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGI("InputQueueCreated: %p -- %p\n", activity, queue);
|
||||
android_app_set_input((struct android_app*)activity->instance, queue);
|
||||
}
|
||||
|
||||
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
|
||||
LOGI("InputQueueDestroyed: %p -- %p\n", activity, queue);
|
||||
android_app_set_input((struct android_app*)activity->instance, NULL);
|
||||
}
|
||||
|
||||
void ANativeActivity_onCreate(ANativeActivity* activity,
|
||||
void* savedState, size_t savedStateSize) {
|
||||
LOGI("Creating: %p\n", activity);
|
||||
activity->callbacks->onDestroy = onDestroy;
|
||||
activity->callbacks->onStart = onStart;
|
||||
activity->callbacks->onResume = onResume;
|
||||
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
|
||||
activity->callbacks->onPause = onPause;
|
||||
activity->callbacks->onStop = onStop;
|
||||
activity->callbacks->onLowMemory = onLowMemory;
|
||||
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
|
||||
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
|
||||
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
|
||||
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
|
||||
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
|
||||
|
||||
activity->instance = android_app_create(activity);
|
||||
}
|
||||
@@ -15,6 +15,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ANDROID_NATIVE_APP_GLUE_H
|
||||
#define _ANDROID_NATIVE_APP_GLUE_H
|
||||
|
||||
#include <poll.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
@@ -22,6 +25,60 @@
|
||||
#include <android/native_activity.h>
|
||||
#include <android/looper.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The native activity interface provided by <android/native_activity.h>
|
||||
* is based on a set of application-provided callbacks that will be called
|
||||
* by the Activity's main thread when certain events occur.
|
||||
*
|
||||
* This means that each one of this callbacks _should_ _not_ block, or they
|
||||
* risk having the system force-close the application. This programming
|
||||
* model is direct, lightweight, but constraining.
|
||||
*
|
||||
* The 'threaded_native_app' static library is used to provide a different
|
||||
* execution model where the application can implement its own main event
|
||||
* loop in a different thread instead. Here's how it works:
|
||||
*
|
||||
* 1/ The application must provide a function named "android_main()" that
|
||||
* will be called when the activity is created, in a new thread that is
|
||||
* distinct from the activity's main thread.
|
||||
*
|
||||
* 2/ android_main() receives a pointer to a valid "android_app" structure
|
||||
* that contains references to other important objects, e.g. the
|
||||
* ANativeActivity obejct instance the application is running in.
|
||||
*
|
||||
* 3/ the "android_app" object holds an ALooper instance that already
|
||||
* listens to two important things:
|
||||
*
|
||||
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
|
||||
* declarations below.
|
||||
*
|
||||
* - input events coming from the AInputQueue attached to the activity.
|
||||
*
|
||||
* Each of these correspond to an ALooper callback that returns a "data"
|
||||
* value of LOOPER_ID_MAIN and LOOPER_ID_EVENT, respectively.
|
||||
*
|
||||
* Your application can use the same ALooper to listen to additionnal
|
||||
* file-descriptors.
|
||||
*
|
||||
* 4/ Whenever you receive a LOOPER_ID_MAIN event from the ALooper, your
|
||||
* code should call the function android_app_read_cmd() to read the
|
||||
* command value and act upon it. This is normally done by calling
|
||||
* android_app_exec_cmd() directly.
|
||||
*
|
||||
* XXX: MAKE THIS STUFF MORE CLEAR !!
|
||||
*
|
||||
* 5/ Whenever you receive a LOOPER_ID_EVENT event from the ALooper, you
|
||||
* should read one event from the AInputQueue with AInputQueue_getEvent().
|
||||
*
|
||||
* See the sample named "native-activity" that comes with the NDK with a
|
||||
* full usage example.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is the interface for the standard glue code of a threaded
|
||||
* application. In this model, the application's code is running
|
||||
@@ -195,3 +252,9 @@ int32_t android_app_exec_cmd(struct android_app* android_app, int8_t cmd);
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern void android_main(struct android_app* app);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ANDROID_NATIVE_APP_GLUE_H */
|
||||
Reference in New Issue
Block a user