am 68267415
: Add new native Looper API.
Merge commit '682674154e3fe88f6061245145f934f25f1a2eb8' into gingerbread-plus-aosp * commit '682674154e3fe88f6061245145f934f25f1a2eb8': Add new native Looper API.
This commit is contained in:
@ -6,7 +6,9 @@ import android.content.pm.ActivityInfo;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.MessageQueue;
|
import android.os.MessageQueue;
|
||||||
import android.view.InputChannel;
|
import android.view.InputChannel;
|
||||||
@ -33,7 +35,8 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
|
|
||||||
private boolean mDestroyed;
|
private boolean mDestroyed;
|
||||||
|
|
||||||
private native int loadNativeCode(String path, MessageQueue queue);
|
private native int loadNativeCode(String path, MessageQueue queue,
|
||||||
|
String internalDataPath, String externalDataPath, int sdkVersion);
|
||||||
private native void unloadNativeCode(int handle);
|
private native void unloadNativeCode(int handle);
|
||||||
|
|
||||||
private native void onStartNative(int handle);
|
private native void onStartNative(int handle);
|
||||||
@ -90,7 +93,11 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
throw new IllegalArgumentException("Unable to find native library: " + libname);
|
throw new IllegalArgumentException("Unable to find native library: " + libname);
|
||||||
}
|
}
|
||||||
|
|
||||||
mNativeHandle = loadNativeCode(path, Looper.myQueue());
|
mNativeHandle = loadNativeCode(path, Looper.myQueue(),
|
||||||
|
getFilesDir().toString(),
|
||||||
|
Environment.getExternalStorageAppFilesDirectory(ai.packageName).toString(),
|
||||||
|
Build.VERSION.SDK_INT);
|
||||||
|
|
||||||
if (mNativeHandle == 0) {
|
if (mNativeHandle == 0) {
|
||||||
throw new IllegalArgumentException("Unable to load native library: " + path);
|
throw new IllegalArgumentException("Unable to load native library: " + path);
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,9 @@ struct NativeCode {
|
|||||||
void* dlhandle;
|
void* dlhandle;
|
||||||
ANativeActivity_createFunc* createActivityFunc;
|
ANativeActivity_createFunc* createActivityFunc;
|
||||||
|
|
||||||
|
String8 internalDataPath;
|
||||||
|
String8 externalDataPath;
|
||||||
|
|
||||||
sp<ANativeWindow> nativeWindow;
|
sp<ANativeWindow> nativeWindow;
|
||||||
jobject inputChannel;
|
jobject inputChannel;
|
||||||
struct MyInputQueue* nativeInputQueue;
|
struct MyInputQueue* nativeInputQueue;
|
||||||
@ -204,7 +207,8 @@ static bool mainWorkCallback(int fd, int events, void* data) {
|
|||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
static jint
|
static jint
|
||||||
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue)
|
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue,
|
||||||
|
jstring internalDataDir, jstring externalDataDir, int sdkVersion)
|
||||||
{
|
{
|
||||||
const char* pathStr = env->GetStringUTFChars(path, NULL);
|
const char* pathStr = env->GetStringUTFChars(path, NULL);
|
||||||
NativeCode* code = NULL;
|
NativeCode* code = NULL;
|
||||||
@ -247,6 +251,19 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQ
|
|||||||
}
|
}
|
||||||
code->activity.env = env;
|
code->activity.env = env;
|
||||||
code->activity.clazz = env->NewGlobalRef(clazz);
|
code->activity.clazz = env->NewGlobalRef(clazz);
|
||||||
|
|
||||||
|
const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
|
||||||
|
code->internalDataPath = dirStr;
|
||||||
|
code->activity.internalDataPath = code->internalDataPath.string();
|
||||||
|
env->ReleaseStringUTFChars(path, dirStr);
|
||||||
|
|
||||||
|
dirStr = env->GetStringUTFChars(externalDataDir, NULL);
|
||||||
|
code->externalDataPath = dirStr;
|
||||||
|
code->activity.externalDataPath = code->externalDataPath.string();
|
||||||
|
env->ReleaseStringUTFChars(path, dirStr);
|
||||||
|
|
||||||
|
code->activity.sdkVersion = sdkVersion;
|
||||||
|
|
||||||
code->createActivityFunc(&code->activity, NULL, 0);
|
code->createActivityFunc(&code->activity, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +437,8 @@ onInputChannelDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const JNINativeMethod g_methods[] = {
|
static const JNINativeMethod g_methods[] = {
|
||||||
{ "loadNativeCode", "(Ljava/lang/String;Landroid/os/MessageQueue;)I", (void*)loadNativeCode_native },
|
{ "loadNativeCode", "(Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;I)I",
|
||||||
|
(void*)loadNativeCode_native },
|
||||||
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
|
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
|
||||||
{ "onStartNative", "(I)V", (void*)onStart_native },
|
{ "onStartNative", "(I)V", (void*)onStart_native },
|
||||||
{ "onResumeNative", "(I)V", (void*)onResume_native },
|
{ "onResumeNative", "(I)V", (void*)onResume_native },
|
||||||
|
@ -51,7 +51,11 @@ private:
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
NativeMessageQueue::NativeMessageQueue() {
|
NativeMessageQueue::NativeMessageQueue() {
|
||||||
|
mPollLoop = PollLoop::getForThread();
|
||||||
|
if (mPollLoop == NULL) {
|
||||||
mPollLoop = new PollLoop();
|
mPollLoop = new PollLoop();
|
||||||
|
PollLoop::setForThread(mPollLoop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeMessageQueue::~NativeMessageQueue() {
|
NativeMessageQueue::~NativeMessageQueue() {
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <ui/Input.h>
|
#include <ui/Input.h>
|
||||||
#include <utils/Errors.h>
|
#include <utils/Errors.h>
|
||||||
|
#include <utils/PollLoop.h>
|
||||||
#include <utils/Timers.h>
|
#include <utils/Timers.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <utils/String8.h>
|
#include <utils/String8.h>
|
||||||
@ -345,11 +346,15 @@ public:
|
|||||||
|
|
||||||
android::status_t consume(android::InputEvent** event);
|
android::status_t consume(android::InputEvent** event);
|
||||||
|
|
||||||
|
void setPollLoop(const android::sp<android::PollLoop>& pollLoop) { mPollLoop = pollLoop; }
|
||||||
|
const android::sp<android::PollLoop> getPollLoop() const { return mPollLoop; }
|
||||||
|
|
||||||
virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
|
virtual void doDefaultKey(android::KeyEvent* keyEvent) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
android::InputConsumer mConsumer;
|
android::InputConsumer mConsumer;
|
||||||
android::PreallocatedInputEventFactory mInputEventFactory;
|
android::PreallocatedInputEventFactory mInputEventFactory;
|
||||||
|
android::sp<android::PollLoop> mPollLoop;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _UI_INPUT_TRANSPORT_H
|
#endif // _UI_INPUT_TRANSPORT_H
|
||||||
|
@ -22,12 +22,22 @@
|
|||||||
|
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
|
||||||
|
#include <android/looper.h>
|
||||||
|
|
||||||
|
struct ALooper : public android::RefBase {
|
||||||
|
protected:
|
||||||
|
virtual ~ALooper() { }
|
||||||
|
|
||||||
|
public:
|
||||||
|
ALooper() { }
|
||||||
|
};
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic file descriptor polling loop based on poll() with callbacks.
|
* A basic file descriptor polling loop based on poll() with callbacks.
|
||||||
*/
|
*/
|
||||||
class PollLoop : public RefBase {
|
class PollLoop : public ALooper {
|
||||||
protected:
|
protected:
|
||||||
virtual ~PollLoop();
|
virtual ~PollLoop();
|
||||||
|
|
||||||
@ -82,6 +92,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setCallback(int fd, int events, Callback callback, void* data = NULL);
|
void setCallback(int fd, int events, Callback callback, void* data = NULL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like setCallback(), but for the NDK callback function.
|
||||||
|
*/
|
||||||
|
void setLooperCallback(int fd, int events, ALooper_callbackFunc* callback, void* data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the callback for a file descriptor, if one exists.
|
* Removes the callback for a file descriptor, if one exists.
|
||||||
*
|
*
|
||||||
@ -100,9 +115,22 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool removeCallback(int fd);
|
bool removeCallback(int fd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the given PollLoop to be associated with the
|
||||||
|
* calling thread. There must be a 1:1 relationship between
|
||||||
|
* PollLoop and thread.
|
||||||
|
*/
|
||||||
|
static void setForThread(const sp<PollLoop>& pollLoop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the PollLoop associated with the calling thread.
|
||||||
|
*/
|
||||||
|
static sp<PollLoop> getForThread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct RequestedCallback {
|
struct RequestedCallback {
|
||||||
Callback callback;
|
Callback callback;
|
||||||
|
ALooper_callbackFunc* looperCallback;
|
||||||
void* data;
|
void* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,6 +138,7 @@ private:
|
|||||||
int fd;
|
int fd;
|
||||||
int events;
|
int events;
|
||||||
Callback callback;
|
Callback callback;
|
||||||
|
ALooper_callbackFunc* looperCallback;
|
||||||
void* data;
|
void* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -130,8 +159,11 @@ private:
|
|||||||
void openWakePipe();
|
void openWakePipe();
|
||||||
void closeWakePipe();
|
void closeWakePipe();
|
||||||
|
|
||||||
|
void setCallbackCommon(int fd, int events, Callback callback,
|
||||||
|
ALooper_callbackFunc* looperCallback, void* data);
|
||||||
ssize_t getRequestIndexLocked(int fd);
|
ssize_t getRequestIndexLocked(int fd);
|
||||||
void wakeAndLock();
|
void wakeAndLock();
|
||||||
|
static void threadDestructor(void *st);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
static bool gHaveTLS = false;
|
||||||
|
static pthread_key_t gTLS = 0;
|
||||||
|
|
||||||
PollLoop::PollLoop() :
|
PollLoop::PollLoop() :
|
||||||
mPolling(false), mWaiters(0) {
|
mPolling(false), mWaiters(0) {
|
||||||
openWakePipe();
|
openWakePipe();
|
||||||
@ -30,6 +34,41 @@ PollLoop::~PollLoop() {
|
|||||||
closeWakePipe();
|
closeWakePipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PollLoop::threadDestructor(void *st) {
|
||||||
|
PollLoop* const self = static_cast<PollLoop*>(st);
|
||||||
|
if (self != NULL) {
|
||||||
|
self->decStrong((void*)threadDestructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollLoop::setForThread(const sp<PollLoop>& pollLoop) {
|
||||||
|
sp<PollLoop> old = getForThread();
|
||||||
|
|
||||||
|
if (pollLoop != NULL) {
|
||||||
|
pollLoop->incStrong((void*)threadDestructor);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_setspecific(gTLS, pollLoop.get());
|
||||||
|
|
||||||
|
if (old != NULL) {
|
||||||
|
old->decStrong((void*)threadDestructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<PollLoop> PollLoop::getForThread() {
|
||||||
|
if (!gHaveTLS) {
|
||||||
|
pthread_mutex_lock(&gTLSMutex);
|
||||||
|
if (pthread_key_create(&gTLS, threadDestructor) != 0) {
|
||||||
|
pthread_mutex_unlock(&gTLSMutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
gHaveTLS = true;
|
||||||
|
pthread_mutex_unlock(&gTLSMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (PollLoop*)pthread_getspecific(gTLS);
|
||||||
|
}
|
||||||
|
|
||||||
void PollLoop::openWakePipe() {
|
void PollLoop::openWakePipe() {
|
||||||
int wakeFds[2];
|
int wakeFds[2];
|
||||||
int result = pipe(wakeFds);
|
int result = pipe(wakeFds);
|
||||||
@ -54,6 +93,7 @@ void PollLoop::openWakePipe() {
|
|||||||
|
|
||||||
RequestedCallback requestedCallback;
|
RequestedCallback requestedCallback;
|
||||||
requestedCallback.callback = NULL;
|
requestedCallback.callback = NULL;
|
||||||
|
requestedCallback.looperCallback = NULL;
|
||||||
requestedCallback.data = NULL;
|
requestedCallback.data = NULL;
|
||||||
mRequestedCallbacks.insertAt(requestedCallback, 0);
|
mRequestedCallbacks.insertAt(requestedCallback, 0);
|
||||||
}
|
}
|
||||||
@ -123,12 +163,14 @@ bool PollLoop::pollOnce(int timeoutMillis) {
|
|||||||
if (revents) {
|
if (revents) {
|
||||||
const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
|
const RequestedCallback& requestedCallback = mRequestedCallbacks.itemAt(i);
|
||||||
Callback callback = requestedCallback.callback;
|
Callback callback = requestedCallback.callback;
|
||||||
|
ALooper_callbackFunc* looperCallback = requestedCallback.looperCallback;
|
||||||
|
|
||||||
if (callback) {
|
if (callback || looperCallback) {
|
||||||
PendingCallback pendingCallback;
|
PendingCallback pendingCallback;
|
||||||
pendingCallback.fd = requestedFd.fd;
|
pendingCallback.fd = requestedFd.fd;
|
||||||
pendingCallback.events = requestedFd.revents;
|
pendingCallback.events = requestedFd.revents;
|
||||||
pendingCallback.callback = callback;
|
pendingCallback.callback = callback;
|
||||||
|
pendingCallback.looperCallback = looperCallback;
|
||||||
pendingCallback.data = requestedCallback.data;
|
pendingCallback.data = requestedCallback.data;
|
||||||
mPendingCallbacks.push(pendingCallback);
|
mPendingCallbacks.push(pendingCallback);
|
||||||
} else {
|
} else {
|
||||||
@ -172,8 +214,14 @@ Done:
|
|||||||
LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
|
LOGD("%p ~ pollOnce - invoking callback for fd %d", this, pendingCallback.fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
|
bool keep = true;
|
||||||
|
if (pendingCallback.callback != NULL) {
|
||||||
|
keep = pendingCallback.callback(pendingCallback.fd, pendingCallback.events,
|
||||||
pendingCallback.data);
|
pendingCallback.data);
|
||||||
|
} else {
|
||||||
|
keep = pendingCallback.looperCallback(pendingCallback.fd, pendingCallback.events,
|
||||||
|
pendingCallback.data) != 0;
|
||||||
|
}
|
||||||
if (! keep) {
|
if (! keep) {
|
||||||
removeCallback(pendingCallback.fd);
|
removeCallback(pendingCallback.fd);
|
||||||
}
|
}
|
||||||
@ -200,11 +248,22 @@ void PollLoop::wake() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
|
void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
|
||||||
|
setCallbackCommon(fd, events, callback, NULL, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollLoop::setLooperCallback(int fd, int events, ALooper_callbackFunc* callback,
|
||||||
|
void* data) {
|
||||||
|
setCallbackCommon(fd, events, NULL, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PollLoop::setCallbackCommon(int fd, int events, Callback callback,
|
||||||
|
ALooper_callbackFunc* looperCallback, void* data) {
|
||||||
|
|
||||||
#if DEBUG_CALLBACKS
|
#if DEBUG_CALLBACKS
|
||||||
LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
|
LOGD("%p ~ setCallback - fd=%d, events=%d", this, fd, events);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (! events || ! callback) {
|
if (! events || (! callback && ! looperCallback)) {
|
||||||
LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
|
LOGE("Invalid attempt to set a callback with no selected poll events or no callback.");
|
||||||
removeCallback(fd);
|
removeCallback(fd);
|
||||||
return;
|
return;
|
||||||
@ -218,6 +277,7 @@ void PollLoop::setCallback(int fd, int events, Callback callback, void* data) {
|
|||||||
|
|
||||||
RequestedCallback requestedCallback;
|
RequestedCallback requestedCallback;
|
||||||
requestedCallback.callback = callback;
|
requestedCallback.callback = callback;
|
||||||
|
requestedCallback.looperCallback = looperCallback;
|
||||||
requestedCallback.data = data;
|
requestedCallback.data = data;
|
||||||
|
|
||||||
ssize_t index = getRequestIndexLocked(fd);
|
ssize_t index = getRequestIndexLocked(fd);
|
||||||
|
@ -8,6 +8,7 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_SRC_FILES:= \
|
LOCAL_SRC_FILES:= \
|
||||||
activity.cpp \
|
activity.cpp \
|
||||||
input.cpp \
|
input.cpp \
|
||||||
|
looper.cpp \
|
||||||
native_window.cpp
|
native_window.cpp
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES := \
|
LOCAL_SHARED_LIBRARIES := \
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <android/input.h>
|
#include <android/input.h>
|
||||||
#include <ui/Input.h>
|
#include <ui/Input.h>
|
||||||
#include <ui/InputTransport.h>
|
#include <ui/InputTransport.h>
|
||||||
|
#include <utils/PollLoop.h>
|
||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
@ -184,8 +185,16 @@ float AMotionEvent_getHistoricalSize(AInputEvent* motion_event, size_t pointer_i
|
|||||||
pointer_index, history_index);
|
pointer_index, history_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AInputQueue_getFd(AInputQueue* queue) {
|
void AInputQueue_attachLooper(AInputQueue* queue, ALooper* looper,
|
||||||
return queue->getConsumer().getChannel()->getReceivePipeFd();
|
ALooper_callbackFunc callback, void* data) {
|
||||||
|
queue->setPollLoop(static_cast<android::PollLoop*>(looper));
|
||||||
|
ALooper_setCallback(looper, queue->getConsumer().getChannel()->getReceivePipeFd(),
|
||||||
|
POLLIN, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AInputQueue_detachLooper(AInputQueue* queue) {
|
||||||
|
queue->getPollLoop()->removeCallback(
|
||||||
|
queue->getConsumer().getChannel()->getReceivePipeFd());
|
||||||
}
|
}
|
||||||
|
|
||||||
int AInputQueue_hasEvents(AInputQueue* queue) {
|
int AInputQueue_hasEvents(AInputQueue* queue) {
|
||||||
|
63
native/android/looper.cpp
Normal file
63
native/android/looper.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "ALooper"
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
|
#include <android/looper.h>
|
||||||
|
#include <utils/PollLoop.h>
|
||||||
|
|
||||||
|
using android::PollLoop;
|
||||||
|
using android::sp;
|
||||||
|
|
||||||
|
ALooper* ALooper_forThread() {
|
||||||
|
return PollLoop::getForThread().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALooper* ALooper_prepare() {
|
||||||
|
sp<PollLoop> loop = PollLoop::getForThread();
|
||||||
|
if (loop == NULL) {
|
||||||
|
loop = new PollLoop();
|
||||||
|
PollLoop::setForThread(loop);
|
||||||
|
}
|
||||||
|
return loop.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ALooper_pollOnce(int timeoutMillis) {
|
||||||
|
sp<PollLoop> loop = PollLoop::getForThread();
|
||||||
|
if (loop == NULL) {
|
||||||
|
LOGW("ALooper_pollOnce: No looper for this thread!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return loop->pollOnce(timeoutMillis) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALooper_acquire(ALooper* looper) {
|
||||||
|
static_cast<PollLoop*>(looper)->incStrong((void*)ALooper_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALooper_release(ALooper* looper) {
|
||||||
|
static_cast<PollLoop*>(looper)->decStrong((void*)ALooper_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ALooper_setCallback(ALooper* looper, int fd, int events,
|
||||||
|
ALooper_callbackFunc* callback, void* data) {
|
||||||
|
static_cast<PollLoop*>(looper)->setLooperCallback(fd, events, callback, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ALooper_removeCallback(ALooper* looper, int fd) {
|
||||||
|
return static_cast<PollLoop*>(looper)->removeCallback(fd) ? 1 : 0;
|
||||||
|
}
|
@ -42,6 +42,7 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <android/keycodes.h>
|
#include <android/keycodes.h>
|
||||||
|
#include <android/looper.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -533,12 +534,15 @@ struct AInputQueue;
|
|||||||
typedef struct AInputQueue AInputQueue;
|
typedef struct AInputQueue AInputQueue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return a file descriptor for the queue, which you
|
* Add this input queue to a looper for processing.
|
||||||
* can use to determine if there are events available. This
|
|
||||||
* is typically used with select() or poll() to multiplex
|
|
||||||
* with other kinds of events.
|
|
||||||
*/
|
*/
|
||||||
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
|
* Returns true if there are one or more events available in the
|
||||||
|
51
native/include/android/looper.h
Normal file
51
native/include/android/looper.h
Normal file
@ -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 <poll.h>
|
||||||
|
|
||||||
|
#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
|
@ -63,6 +63,21 @@ typedef struct ANativeActivity {
|
|||||||
*/
|
*/
|
||||||
jobject clazz;
|
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
|
* 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
|
* the framework, but can be set by the application to its own instance
|
||||||
|
Reference in New Issue
Block a user