From 02215b36dde381f0b48ba51bfea405f5a6b01e46 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Fri, 2 Jul 2010 18:54:33 -0700 Subject: [PATCH] Update to use new looper API. Also need to put back the stub Java class for now, as the build system still seems to require it. Change-Id: I31917a1fc7c0bf8cd928969125f94d55c59d42f8 --- .../arch-arm/usr/include/android/input.h | 14 +- .../arch-arm/usr/include/android/looper.h | 51 +++++ .../usr/include/android/native_activity.h | 15 ++ .../android-9/arch-arm/usr/lib/libandroid.so | Bin 9492 -> 9524 bytes ndk/samples/native-activity/jni/glutils.c | 2 + ndk/samples/native-activity/jni/main.c | 181 ++++++++++-------- ndk/samples/native-activity/src/Dummy.java | 4 + 7 files changed, 181 insertions(+), 86 deletions(-) create mode 100644 ndk/platforms/android-9/arch-arm/usr/include/android/looper.h create mode 100644 ndk/samples/native-activity/src/Dummy.java diff --git a/ndk/platforms/android-9/arch-arm/usr/include/android/input.h b/ndk/platforms/android-9/arch-arm/usr/include/android/input.h index 76176624a..75be85abb 100644 --- a/ndk/platforms/android-9/arch-arm/usr/include/android/input.h +++ b/ndk/platforms/android-9/arch-arm/usr/include/android/input.h @@ -42,6 +42,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -533,12 +534,15 @@ struct AInputQueue; typedef struct AInputQueue AInputQueue; /* - * Return a file descriptor for the queue, which you - * can use to determine if there are events available. This - * is typically used with select() or poll() to multiplex - * with other kinds of events. + * Add this input queue to a looper for processing. */ -int AInputQueue_getFd(AInputQueue* queue); +void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper, + ALooper_callbackFunc callback, void* data); + +/* + * Remove the input queue from the looper it is currently attached to. + */ +void AInputQueue_detachLooper(AInputQueue* queue); /* * Returns true if there are one or more events available in the diff --git a/ndk/platforms/android-9/arch-arm/usr/include/android/looper.h b/ndk/platforms/android-9/arch-arm/usr/include/android/looper.h new file mode 100644 index 000000000..90a89838a --- /dev/null +++ b/ndk/platforms/android-9/arch-arm/usr/include/android/looper.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +#ifndef ANDROID_LOOPER_H +#define ANDROID_LOOPER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct ALooper; +typedef struct ALooper ALooper; + +typedef int ALooper_callbackFunc(int fd, int events, void* data); + +ALooper* ALooper_forThread(); + +ALooper* ALooper_prepare(); + +int32_t ALooper_pollOnce(int timeoutMillis); + +void ALooper_acquire(ALooper* looper); + +void ALooper_release(ALooper* looper); + +void ALooper_setCallback(ALooper* looper, int fd, int events, + ALooper_callbackFunc* callback, void* data); + +int32_t ALooper_removeCallback(ALooper* looper, int fd); + +#ifdef __cplusplus +}; +#endif + +#endif // ANDROID_NATIVE_WINDOW_H diff --git a/ndk/platforms/android-9/arch-arm/usr/include/android/native_activity.h b/ndk/platforms/android-9/arch-arm/usr/include/android/native_activity.h index bf5c641fc..a31c5af74 100644 --- a/ndk/platforms/android-9/arch-arm/usr/include/android/native_activity.h +++ b/ndk/platforms/android-9/arch-arm/usr/include/android/native_activity.h @@ -63,6 +63,21 @@ typedef struct ANativeActivity { */ jobject clazz; + /** + * Path to this application's internal data directory. + */ + const char* internalDataPath; + + /** + * Path to this application's external (removable/mountable) data directory. + */ + const char* externalDataPath; + + /** + * The platform's SDK version code. + */ + int32_t sdkVersion; + /** * This is the native instance of the application. It is not used by * the framework, but can be set by the application to its own instance diff --git a/ndk/platforms/android-9/arch-arm/usr/lib/libandroid.so b/ndk/platforms/android-9/arch-arm/usr/lib/libandroid.so index ffef23da82f82f481b53cd6a7f549fa44a5ffad1..d185a8fb16fa3a48b212b52f681450f292d3de71 100644 GIT binary patch literal 9524 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 delta 2694 zcma);eQXp(7{+JryQN33z1o&a?cQBWua!c}XN!Oo%3>Rkmed3d#40ux6F>}&NFaO0 zfS?#!hu{Gv)R<_C1+N~BAE8pw5Tf{jQBx3;LV|yguxV9tBH;SG+dZ7zUrzG$d4KQB zygReIH`|j9`x`nGKEE@t#5J75*l)`p&G>ggHR$L07CvNf&M4v6ciIS77o}^7h zP-#JSG6|n-#k1i)D|W(bthfpu5?MCClkQ(NMIvH%@=USIUZiD?Z#X&iS!nxKFSC7uTk zNZbrAk>+mzSAgkmQTLvaGyh7p|;3kRFZHzqzPHvzWycV3i zU=4UP81J;XfJebQ!9j~#Y#L*|QsM;+_(q!WI{1pj-Qb&GmsQ|9@Lljki~j(7v;N~L zcHA*AhL{U@99#i@z~c52Bvwd?PVfe4!b$LsEOFLZq#+xzrcI-jup~1;>mv7$Eby6yB7=JHRc{{M{+MKZUze_-*cr+tM5k z(dd0cRC*P0$y=3GTfg!7_AO2At?jK(KHIuQeMVGHjK({B@A2GxTq}19PABp(_D)_V z)a=qpm3U!@s&HbH&%{YhUL(HE4r=G{p0Tt0uJW(;UOhK<>RK`$lH!l0I3~qCQrs=Y zQ7P__;@wgl8IN<#3vUHD*uJZbbzHk;7}p!)7yX}e?Ppz4eS_M7L-nexyyAkV?Ugo< z8ePW2r5D1gkvOmC#{+GO`dV9=+Oe#7#NJn?Dyr?ck@&^19}cVjF%LHqL%O%#+u&4Q zsuw)iBmew9@6d6#{PgAxkgF~DR)M9sVscyf;Pxb$288^htS*s-p30SbjJ)H z4XDobMxqBL7GluofTNIw_Qc%kgcb$MG!pNk#Av_!ct8!Su0A7iz;GW_R8N(W*scfa z0}U=L#APjHD>g`ZchvIJYTz#2t@`2)vz+~ek=SH7qCV`a z5`E2jW__l)GdmT0%Sbfp<9Uqfr((_K1y<`TM~zB8;yhH|k`@~s3}aKR&@dkTDtOU= z-P+(H!ye`9c_-bKIb0V?UVh$UorPV$4&F*vczMQYu23yU%oqPUzlJxhxov2%SWl$I z^jPH1opJWuHMC=y{gDW~*WDl450Aa?i8TIWXg$bxz@vttb-}yfJ@9V$$@r0ib>ndRp!{|P>gI<8m=-SULxhUFP3NFRk9xA;_9 zB_`W4%4gxz{QnexIxvUxS>j-@Xa=pAL`OF5m>R8=cCZ|x9PN&FLJGRY_22_(bR$Ts zMOLUNEqU3f=nwhD@{qRzYdH^npDc+A$s?V%N16e3;U;$Z#ja4$)r|YvoFh(zf@$~u uKNJ^3M|rhbbZ>EnlMdWQaiqA^jPlL= + const char *EGLstrerror(EGLint err) { switch (err) { case EGL_SUCCESS: return "EGL_SUCCESS"; diff --git a/ndk/samples/native-activity/jni/main.c b/ndk/samples/native-activity/jni/main.c index 0b784154a..3d2faeef9 100644 --- a/ndk/samples/native-activity/jni/main.c +++ b/ndk/samples/native-activity/jni/main.c @@ -42,12 +42,14 @@ struct engine { int running; int destroyed; + ALooper* looper; AInputQueue* inputQueue; ANativeWindow* window; AInputQueue* pendingInputQueue; ANativeWindow* pendingWindow; // private to engine thread. + int destroyRequested; int animating; EGLDisplay display; EGLSurface surface; @@ -159,105 +161,121 @@ static int engine_term_display(struct engine* engine) { engine->surface = EGL_NO_SURFACE; } +static int engine_process_event(int fd, int events, void* param) { + struct engine* engine = (struct engine*)param; + + AInputEvent* event = NULL; + if (AInputQueue_getEvent(engine->inputQueue, &event) >= 0) { + LOGI("New input event: type=%d\n", AInputEvent_getType(event)); + if (AInputEvent_getType(event) == INPUT_EVENT_TYPE_MOTION) { + engine->animating = 1; + engine->x = AMotionEvent_getX(event, 0); + engine->y = AMotionEvent_getY(event, 0); + AInputQueue_finishEvent(engine->inputQueue, event, 1); + } else { + AInputQueue_finishEvent(engine->inputQueue, event, 0); + } + } else { + LOGI("Failure reading next input event: %s\n", strerror(errno)); + } + + return 1; +} + +static int engine_process_cmd(int fd, int events, void* param) { + struct engine* engine = (struct engine*)param; + + int8_t cmd; + if (read(engine->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { + switch (cmd) { + case ENGINE_CMD_INPUT_CHANGED: + LOGI("Engine: ENGINE_CMD_INPUT_CHANGED\n"); + pthread_mutex_lock(&engine->mutex); + if (engine->inputQueue != NULL) { + AInputQueue_detachLooper(engine->inputQueue); + } + engine->inputQueue = engine->pendingInputQueue; + if (engine->inputQueue != NULL) { + LOGI("Attaching input queue to looper"); + AInputQueue_attachLooper(engine->inputQueue, + engine->looper, engine_process_event, engine); + } + pthread_cond_broadcast(&engine->cond); + pthread_mutex_unlock(&engine->mutex); + break; + + case ENGINE_CMD_WINDOW_CHANGED: + LOGI("Engine: ENGINE_CMD_WINDOW_CHANGED\n"); + engine_term_display(engine); + pthread_mutex_lock(&engine->mutex); + engine->window = engine->pendingWindow; + pthread_cond_broadcast(&engine->cond); + pthread_mutex_unlock(&engine->mutex); + if (engine->window != NULL) { + engine_init_display(engine); + engine_draw_frame(engine); + } + break; + + case ENGINE_CMD_LOST_FOCUS: + engine->animating = 0; + engine_draw_frame(engine); + break; + + case ENGINE_CMD_DESTROY: + LOGI("Engine: ENGINE_CMD_DESTROY\n"); + engine->destroyRequested = 1; + break; + } + } else { + LOGW("No data on command pipe!"); + } + + return 1; +} + static void* engine_entry(void* param) { struct engine* engine = (struct engine*)param; - struct pollfd pfd[2]; - int numfd; + + ALooper* looper = ALooper_prepare(); + ALooper_setCallback(looper, engine->msgread, POLLIN, engine_process_cmd, engine); + engine->looper = looper; pthread_mutex_lock(&engine->mutex); engine->running = 1; pthread_cond_broadcast(&engine->cond); pthread_mutex_unlock(&engine->mutex); - // loop waiting for stuff to do. we wait for input events or - // commands from the main thread. - - pfd[0].fd = engine->msgread; - pfd[0].events = POLLIN; - pfd[0].revents = 0; + // loop waiting for stuff to do. while (1) { - if (engine->inputQueue != NULL) { - numfd = 2; - pfd[1].fd = AInputQueue_getFd(engine->inputQueue); - pfd[1].events = POLLIN; - } else { - numfd = 1; + // Read all pending events. + while (ALooper_pollOnce(engine->animating ? 0 : -1)) { + ; } - pfd[0].revents = 0; - pfd[1].revents = 0; - int nfd = poll(pfd, numfd, engine->animating ? 0 : -1); - if (nfd == 0 && engine->animating) { - // There is no work to do -- step next animation. + if (engine->destroyRequested) { + LOGI("Engine thread destroy requested!"); + pthread_mutex_lock(&engine->mutex); + engine_term_display(engine); + if (engine->inputQueue != NULL) { + AInputQueue_detachLooper(engine->inputQueue); + } + engine->destroyed = 1; + pthread_cond_broadcast(&engine->cond); + pthread_mutex_unlock(&engine->mutex); + // Can't touch engine object after this. + return NULL; // EXIT THREAD + } + + if (engine->animating) { + // Done with events; draw next animation frame. engine->angle += .01f; if (engine->angle > 1) { engine->angle = 0; } engine_draw_frame(engine); } - if (nfd < 0) { - LOGI("Engine error in poll: %s\n", strerror(errno)); - // Should cleanly exit! - continue; - } - - if (pfd[0].revents == POLLIN) { - int8_t cmd; - if (read(engine->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) { - switch (cmd) { - case ENGINE_CMD_INPUT_CHANGED: - LOGI("Engine: ENGINE_CMD_INPUT_CHANGED\n"); - pthread_mutex_lock(&engine->mutex); - engine->inputQueue = engine->pendingInputQueue; - pthread_cond_broadcast(&engine->cond); - pthread_mutex_unlock(&engine->mutex); - break; - case ENGINE_CMD_WINDOW_CHANGED: - LOGI("Engine: ENGINE_CMD_WINDOW_CHANGED\n"); - pthread_mutex_lock(&engine->mutex); - engine_term_display(engine); - engine->window = engine->pendingWindow; - if (engine->window != NULL) { - engine_init_display(engine); - engine_draw_frame(engine); - } - pthread_cond_broadcast(&engine->cond); - pthread_mutex_unlock(&engine->mutex); - break; - case ENGINE_CMD_LOST_FOCUS: - engine->animating = 0; - engine_draw_frame(engine); - break; - case ENGINE_CMD_DESTROY: - LOGI("Engine: ENGINE_CMD_DESTROY\n"); - pthread_mutex_lock(&engine->mutex); - engine_term_display(engine); - engine->destroyed = 1; - pthread_cond_broadcast(&engine->cond); - pthread_mutex_unlock(&engine->mutex); - // Can't touch engine object after this. - return NULL; // EXIT THREAD - } - } else { - LOGI("Failure reading engine cmd: %s\n", strerror(errno)); - } - - } else if (engine->inputQueue != NULL && pfd[1].revents == POLLIN) { - AInputEvent* event = NULL; - if (AInputQueue_getEvent(engine->inputQueue, &event) >= 0) { - LOGI("New input event: type=%d\n", AInputEvent_getType(event)); - if (AInputEvent_getType(event) == INPUT_EVENT_TYPE_MOTION) { - engine->animating = 1; - engine->x = AMotionEvent_getX(event, 0); - engine->y = AMotionEvent_getY(event, 0); - engine_draw_frame(engine); - } - AInputQueue_finishEvent(engine->inputQueue, event, 0); - } else { - LOGI("Failure reading next input event: %s\n", strerror(errno)); - } - } } } @@ -329,6 +347,7 @@ static void engine_destroy(struct engine* engine) { close(engine->msgwrite); pthread_cond_destroy(&engine->cond); pthread_mutex_destroy(&engine->mutex); + free(engine); } // -------------------------------------------------------------------- diff --git a/ndk/samples/native-activity/src/Dummy.java b/ndk/samples/native-activity/src/Dummy.java new file mode 100644 index 000000000..4160c66b9 --- /dev/null +++ b/ndk/samples/native-activity/src/Dummy.java @@ -0,0 +1,4 @@ + +// Only needed for the build system. +public class Dummy { +}