You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
make Looper, Handler, and MessageQueue work properly
this for example makes Unity apps not steal the main thread, hanging Gtk.
This commit is contained in:
@@ -59,6 +59,7 @@ libandroid_so = shared_library('android', [
|
||||
libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||
'src/api-impl-jni/egl/com_google_android_gles_jni_EGLImpl.c',
|
||||
'src/api-impl-jni/android_os_Environment.c',
|
||||
'src/api-impl-jni/android_os_MessageQueue.c',
|
||||
'src/api-impl-jni/android_os_SystemClock.c',
|
||||
'src/api-impl-jni/android_view_Window.c',
|
||||
'src/api-impl-jni/util.c',
|
||||
|
||||
62
src/api-impl-jni/android_os_MessageQueue.c
Normal file
62
src/api-impl-jni/android_os_MessageQueue.c
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "defines.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* TODO put these in a header */
|
||||
typedef void ALooper;
|
||||
ALooper * ALooper_prepare(void);
|
||||
void ALooper_wake(ALooper *looper);
|
||||
bool ALooper_isPolling(ALooper *looper);
|
||||
int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
||||
|
||||
struct native_message_queue {
|
||||
ALooper *looper;
|
||||
bool in_callback;
|
||||
};
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_android_os_MessageQueue_nativeInit(JNIEnv *env, jclass this)
|
||||
{
|
||||
struct native_message_queue *message_queue = malloc(sizeof(struct native_message_queue));
|
||||
|
||||
message_queue->in_callback = false;
|
||||
message_queue->looper = ALooper_prepare();
|
||||
|
||||
return _INTPTR(message_queue);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativeDestroy(JNIEnv *env, jclass this, jlong ptr)
|
||||
{
|
||||
struct native_message_queue *message_queue = _PTR(ptr);
|
||||
|
||||
free(message_queue);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativePollOnce(JNIEnv *env, jclass this, jlong ptr, jint timeout_millis)
|
||||
{
|
||||
struct native_message_queue *message_queue = _PTR(ptr);
|
||||
|
||||
// printf("Java_android_os_MessageQueue_nativePollOnce: entry (timeout: %d)\n", timeout_millis);
|
||||
message_queue->in_callback = true;
|
||||
ALooper_pollOnce(timeout_millis, NULL, NULL, NULL);
|
||||
message_queue->in_callback = false;
|
||||
// printf("Java_android_os_MessageQueue_nativePollOnce: exit\n");
|
||||
|
||||
/* TODO: what's with the exception stuff */
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativeWake(JNIEnv *env, jclass this, jlong ptr)
|
||||
{
|
||||
struct native_message_queue *message_queue = _PTR(ptr);
|
||||
|
||||
ALooper_wake(message_queue->looper);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_android_os_MessageQueue_nativeIsIdling(JNIEnv *env, jclass this, jlong ptr)
|
||||
{
|
||||
struct native_message_queue *message_queue = _PTR(ptr);
|
||||
|
||||
return ALooper_isPolling(message_queue->looper);
|
||||
}
|
||||
@@ -1,3 +1,6 @@
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "generated_headers/android_os_SystemClock.h"
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_android_os_SystemClock_elapsedRealtime(JNIEnv *env, jclass this)
|
||||
@@ -5,3 +8,10 @@ JNIEXPORT jlong JNICALL Java_android_os_SystemClock_elapsedRealtime(JNIEnv *env,
|
||||
printf("FIXME: Java_android_os_SystemClock_elapsedRealtime: returning 0\n");
|
||||
return 0; // FIXME
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_android_os_SystemClock_uptimeMillis(JNIEnv *env, jclass this)
|
||||
{
|
||||
struct timespec t;
|
||||
clock_gettime(CLOCK_REALTIME, &t);
|
||||
return t.tv_sec * 1000 + lround(t.tv_nsec / 1e6);
|
||||
}
|
||||
|
||||
@@ -10,42 +10,42 @@ extern "C" {
|
||||
/*
|
||||
* Class: android_os_MessageQueue
|
||||
* Method: nativeInit
|
||||
* Signature: ()I
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jint JNICALL Java_android_os_MessageQueue_nativeInit
|
||||
JNIEXPORT jlong JNICALL Java_android_os_MessageQueue_nativeInit
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: android_os_MessageQueue
|
||||
* Method: nativeDestroy
|
||||
* Signature: (I)V
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativeDestroy
|
||||
(JNIEnv *, jclass, jint);
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_os_MessageQueue
|
||||
* Method: nativePollOnce
|
||||
* Signature: (II)V
|
||||
* Signature: (JI)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativePollOnce
|
||||
(JNIEnv *, jclass, jint, jint);
|
||||
(JNIEnv *, jclass, jlong, jint);
|
||||
|
||||
/*
|
||||
* Class: android_os_MessageQueue
|
||||
* Method: nativeWake
|
||||
* Signature: (I)V
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_os_MessageQueue_nativeWake
|
||||
(JNIEnv *, jclass, jint);
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_os_MessageQueue
|
||||
* Method: nativeIsIdling
|
||||
* Signature: (I)Z
|
||||
* Signature: (J)Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_android_os_MessageQueue_nativeIsIdling
|
||||
(JNIEnv *, jclass, jint);
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -15,6 +15,14 @@ extern "C" {
|
||||
JNIEXPORT jboolean JNICALL Java_android_os_SystemClock_setCurrentTimeMillis
|
||||
(JNIEnv *, jclass, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_os_SystemClock
|
||||
* Method: uptimeMillis
|
||||
* Signature: ()J
|
||||
*/
|
||||
JNIEXPORT jlong JNICALL Java_android_os_SystemClock_uptimeMillis
|
||||
(JNIEnv *, jclass);
|
||||
|
||||
/*
|
||||
* Class: android_os_SystemClock
|
||||
* Method: elapsedRealtime
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -102,6 +104,12 @@ public class Activity extends Context {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
System.out.println("- onCreate - yay!");
|
||||
|
||||
/* TODO: this probably belongs elsewhere, but this is our entry point for better or worse */
|
||||
Looper looper = Looper.myLooper();
|
||||
if(looper == null) {
|
||||
Looper.prepareMainLooper();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +220,11 @@ public class Activity extends Context {
|
||||
}
|
||||
|
||||
public final void runOnUiThread(Runnable action) {
|
||||
action.run(); // FIXME: running synchronously for now
|
||||
if(Looper.myLooper() == Looper.getMainLooper()) {
|
||||
action.run();
|
||||
} else {
|
||||
new Handler(Looper.getMainLooper()).post(action);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.view.WindowManager;
|
||||
import android.view.WindowManagerImpl;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
public class Context extends Object {
|
||||
@@ -138,8 +139,14 @@ public class Context extends Object {
|
||||
}
|
||||
|
||||
public Looper getMainLooper() {
|
||||
System.out.println("returning the main Looper, most definitely doing just that!");
|
||||
return new Looper();
|
||||
/* TODO: this is not what AOSP does, which could be a problem */
|
||||
Looper looper = Looper.myLooper();
|
||||
if(looper == null) {
|
||||
Looper.prepare();
|
||||
looper = Looper.myLooper();
|
||||
}
|
||||
|
||||
return looper;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
@@ -251,9 +258,12 @@ public class Context extends Object {
|
||||
return new ComponentName("", "");
|
||||
}
|
||||
|
||||
// FIXME - it should be *trivial* to do actually implement this
|
||||
public FileInputStream openFileInput(String name) {
|
||||
return null;
|
||||
// TODO: do these both work? make them look more alike
|
||||
public FileInputStream openFileInput(String name) throws FileNotFoundException {
|
||||
System.out.println("openFileInput called for: '" + name + "'");
|
||||
File file = new File(getFilesDir(), name);
|
||||
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
|
||||
public FileOutputStream openFileOutput(String name, int mode) throws java.io.FileNotFoundException {
|
||||
|
||||
@@ -738,6 +738,7 @@ public final class Bundle implements Cloneable {
|
||||
*/
|
||||
public boolean getBoolean(String key, boolean defaultValue) {
|
||||
Object o = mMap.get(key);
|
||||
System.out.println("bundle.getBoolean(" + key + ", " + defaultValue + ") called");
|
||||
if (o == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ public class Handler {
|
||||
*/
|
||||
public Handler(Looper looper, Callback callback, boolean async) {
|
||||
mLooper = looper;
|
||||
mQueue = null /*looper.mQueue*/;
|
||||
mQueue = looper.mQueue;
|
||||
mCallback = callback;
|
||||
mAsynchronous = async;
|
||||
}
|
||||
@@ -316,9 +316,7 @@ public class Handler {
|
||||
* looper processing the message queue is exiting.
|
||||
*/
|
||||
public final boolean post(Runnable r) {
|
||||
// return sendMessageDelayed(getPostMessage(r), 0);
|
||||
r.run();
|
||||
return true;
|
||||
return sendMessageDelayed(getPostMessage(r), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -571,29 +569,14 @@ public class Handler {
|
||||
* occurs then the message will be dropped.
|
||||
*/
|
||||
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
|
||||
/* MessageQueue queue = mQueue;
|
||||
MessageQueue queue = mQueue;
|
||||
if (queue == null) {
|
||||
RuntimeException e = new RuntimeException(
|
||||
this + " sendMessageAtTime() called with no mQueue");
|
||||
Log.w("Looper", e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
return enqueueMessage(queue, msg, uptimeMillis);*/
|
||||
if (mCallback != null) {
|
||||
// System.out.println("Handler.sendMessageAtTime: directly calling mCallback.handleMessage)");
|
||||
if (msg.callback != null) {
|
||||
msg.callback.run();
|
||||
}
|
||||
return mCallback.handleMessage(msg);
|
||||
} else {
|
||||
// System.out.println("Handler.sendMessageAtTime: not directly calling mCallback.handleMessage - mCallback is null)");
|
||||
/* do this in this case as well?
|
||||
if(msg.callback != null) {
|
||||
msg.callback.run();
|
||||
}
|
||||
*/
|
||||
return true; // false?
|
||||
}
|
||||
return enqueueMessage(queue, msg, uptimeMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,15 +592,14 @@ public class Handler {
|
||||
* looper processing the message queue is exiting.
|
||||
*/
|
||||
public final boolean sendMessageAtFrontOfQueue(Message msg) {
|
||||
/*MessageQueue queue = mQueue;
|
||||
MessageQueue queue = mQueue;
|
||||
if (queue == null) {
|
||||
RuntimeException e = new RuntimeException(
|
||||
this + " sendMessageAtTime() called with no mQueue");
|
||||
Log.w("Looper", e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
return enqueueMessage(queue, msg, 0);*/
|
||||
return true;
|
||||
return enqueueMessage(queue, msg, 0);
|
||||
}
|
||||
|
||||
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
|
||||
|
||||
@@ -1,19 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2006 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.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* Handy class for starting a new thread that has a looper. The looper can then be
|
||||
* used to create handler classes. Note that start() must still be called.
|
||||
*/
|
||||
public class HandlerThread extends Thread {
|
||||
String name;
|
||||
|
||||
public HandlerThread() {}
|
||||
int mPriority;
|
||||
int mTid = -1;
|
||||
Looper mLooper;
|
||||
|
||||
public HandlerThread(String name) {
|
||||
this.name = name;
|
||||
super(name);
|
||||
mPriority = Process.THREAD_PRIORITY_DEFAULT;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// if(name.equals("FlurryAgent")) { return; }
|
||||
/**
|
||||
* Constructs a HandlerThread.
|
||||
* @param name
|
||||
* @param priority The priority to run the thread at. The value supplied must be from
|
||||
* {@link android.os.Process} and not from java.lang.Thread.
|
||||
*/
|
||||
public HandlerThread(String name, int priority) {
|
||||
super(name);
|
||||
mPriority = priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call back method that can be explicitly overridden if needed to execute some
|
||||
* setup before Looper loops.
|
||||
*/
|
||||
protected void onLooperPrepared() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mTid = Process.myTid();
|
||||
Looper.prepare();
|
||||
synchronized (this) {
|
||||
mLooper = Looper.myLooper();
|
||||
notifyAll();
|
||||
}
|
||||
Process.setThreadPriority(mPriority);
|
||||
onLooperPrepared();
|
||||
Looper.loop();
|
||||
mTid = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Looper associated with this thread. If this thread not been started
|
||||
* or for any reason is isAlive() returns false, this method will return null. If this thread
|
||||
* has been started, this method will block until the looper has been initialized.
|
||||
* @return The looper.
|
||||
*/
|
||||
public Looper getLooper() {
|
||||
return new Looper();
|
||||
if (!isAlive()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the thread has been started, wait until the looper has been created.
|
||||
synchronized (this) {
|
||||
while (isAlive() && mLooper == null) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return mLooper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quits the handler thread's looper.
|
||||
* <p>
|
||||
* Causes the handler thread's looper to terminate without processing any
|
||||
* more messages in the message queue.
|
||||
* </p><p>
|
||||
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
|
||||
* For example, the {@link Handler#sendMessage(Message)} method will return false.
|
||||
* </p><p class="note">
|
||||
* Using this method may be unsafe because some messages may not be delivered
|
||||
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
|
||||
* that all pending work is completed in an orderly manner.
|
||||
* </p>
|
||||
*
|
||||
* @return True if the looper looper has been asked to quit or false if the
|
||||
* thread had not yet started running.
|
||||
*
|
||||
* @see #quitSafely
|
||||
*/
|
||||
public boolean quit() {
|
||||
Looper looper = getLooper();
|
||||
if (looper != null) {
|
||||
looper.quit();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quits the handler thread's looper safely.
|
||||
* <p>
|
||||
* Causes the handler thread's looper to terminate as soon as all remaining messages
|
||||
* in the message queue that are already due to be delivered have been handled.
|
||||
* Pending delayed messages with due times in the future will not be delivered.
|
||||
* </p><p>
|
||||
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
|
||||
* For example, the {@link Handler#sendMessage(Message)} method will return false.
|
||||
* </p><p>
|
||||
* If the thread has not been started or has finished (that is if
|
||||
* {@link #getLooper} returns null), then false is returned.
|
||||
* Otherwise the looper is asked to quit and true is returned.
|
||||
* </p>
|
||||
*
|
||||
* @return True if the looper looper has been asked to quit or false if the
|
||||
* thread had not yet started running.
|
||||
*/
|
||||
public boolean quitSafely() {
|
||||
Looper looper = getLooper();
|
||||
if (looper != null) {
|
||||
looper.quitSafely();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of this thread. See Process.myTid().
|
||||
*/
|
||||
public int getThreadId() {
|
||||
return mTid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,13 +53,6 @@ import android.util.Printer;
|
||||
public final class Looper {
|
||||
private static final String TAG = "Looper";
|
||||
|
||||
// FIXME
|
||||
public Looper() {
|
||||
mQueue = null;
|
||||
mThread = Thread.currentThread();
|
||||
System.out.println("making a fake Looper object, let's hope noone tries to actually use it");
|
||||
}
|
||||
|
||||
// sThreadLocal.get() will return null unless you've called prepare().
|
||||
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
|
||||
private static Looper sMainLooper; // guarded by Looper.class
|
||||
@@ -84,7 +77,7 @@ public final class Looper {
|
||||
if (sThreadLocal.get() != null) {
|
||||
throw new RuntimeException("Only one Looper may be created per thread");
|
||||
}
|
||||
sThreadLocal.set(new Looper(/*quitAllowed*/));
|
||||
sThreadLocal.set(new Looper(quitAllowed));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,10 +100,9 @@ public final class Looper {
|
||||
* Returns the application's main looper, which lives in the main thread of the application.
|
||||
*/
|
||||
public static Looper getMainLooper() {
|
||||
return new Looper();
|
||||
/* synchronized (Looper.class) {
|
||||
synchronized (Looper.class) {
|
||||
return sMainLooper;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,8 +110,7 @@ public final class Looper {
|
||||
* {@link #quit()} to end the loop.
|
||||
*/
|
||||
public static void loop() {
|
||||
System.out.println("oops, Looper.loop called... and we don't implement that");
|
||||
/*final Looper me = myLooper();
|
||||
final Looper me = myLooper();
|
||||
if (me == null) {
|
||||
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
|
||||
}
|
||||
@@ -127,8 +118,8 @@ public final class Looper {
|
||||
|
||||
// Make sure the identity of this thread is that of the local process,
|
||||
// and keep track of what that identity token actually is.
|
||||
// Binder.clearCallingIdentity();
|
||||
// final long ident = Binder.clearCallingIdentity();
|
||||
// Binder.clearCallingIdentity();
|
||||
// final long ident = Binder.clearCallingIdentity();
|
||||
|
||||
for (;;) {
|
||||
Message msg = queue.next(); // might block
|
||||
@@ -152,17 +143,13 @@ public final class Looper {
|
||||
|
||||
// Make sure that during the course of dispatching the
|
||||
// identity of the thread wasn't corrupted.
|
||||
// final long newIdent = Binder.clearCallingIdentity();
|
||||
/* if (ident != newIdent) {
|
||||
Log.wtf(TAG, "Thread identity changed from 0x"
|
||||
+ Long.toHexString(ident) + " to 0x"
|
||||
+ Long.toHexString(newIdent) + " while dispatching to "
|
||||
+ msg.target.getClass().getName() + " "
|
||||
+ msg.callback + " what=" + msg.what);
|
||||
}* /
|
||||
|
||||
/* final long newIdent = Binder.clearCallingIdentity();
|
||||
if (ident != newIdent) {
|
||||
Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what);
|
||||
}
|
||||
*/
|
||||
msg.recycle();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,11 +157,7 @@ public final class Looper {
|
||||
* null if the calling thread is not associated with a Looper.
|
||||
*/
|
||||
public static Looper myLooper() {
|
||||
return new Looper();
|
||||
/* if(sThreadLocal.get() == null) {
|
||||
prepare(false);
|
||||
}
|
||||
return sThreadLocal.get();*/
|
||||
return sThreadLocal.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,8 +276,7 @@ public final class Looper {
|
||||
* Return the Thread associated with this Looper.
|
||||
*/
|
||||
public Thread getThread() {
|
||||
return Thread.currentThread(); // ugly hack
|
||||
// return mThread;
|
||||
return mThread;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,7 +34,7 @@ public final class MessageQueue {
|
||||
private final boolean mQuitAllowed;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int mPtr; // used by native code
|
||||
private long mPtr; // used by native code
|
||||
|
||||
Message mMessages;
|
||||
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();
|
||||
@@ -48,11 +48,11 @@ public final class MessageQueue {
|
||||
// Barriers are indicated by messages with a null target whose arg1 field carries the token.
|
||||
private int mNextBarrierToken;
|
||||
|
||||
private native static int nativeInit();
|
||||
private native static void nativeDestroy(int ptr);
|
||||
private native static void nativePollOnce(int ptr, int timeoutMillis);
|
||||
private native static void nativeWake(int ptr);
|
||||
private native static boolean nativeIsIdling(int ptr);
|
||||
private native static long nativeInit();
|
||||
private native static void nativeDestroy(long ptr);
|
||||
private native static void nativePollOnce(long ptr, int timeoutMillis);
|
||||
private native static void nativeWake(long ptr);
|
||||
private native static boolean nativeIsIdling(long ptr);
|
||||
|
||||
/**
|
||||
* Callback interface for discovering when a thread is going to block
|
||||
|
||||
@@ -105,16 +105,13 @@ public final class SystemClock {
|
||||
* @param ms to sleep before returning, in milliseconds of uptime.
|
||||
*/
|
||||
public static void sleep(long ms) {
|
||||
System.out.println("!!! sleep(...) doesn't work, need to implement uptimeMillis");
|
||||
/*
|
||||
long start = uptimeMillis();
|
||||
long duration = ms;
|
||||
boolean interrupted = false;
|
||||
do {
|
||||
try {
|
||||
Thread.sleep(duration);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
duration = start + ms - uptimeMillis();
|
||||
@@ -126,7 +123,7 @@ public final class SystemClock {
|
||||
// call to Thread.sleep() or Object.wait() will be interrupted.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
*/}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current wall time, in milliseconds. Requires the calling
|
||||
@@ -141,9 +138,7 @@ public final class SystemClock {
|
||||
*
|
||||
* @return milliseconds of non-sleep uptime since boot.
|
||||
*/
|
||||
/*native */ public static long uptimeMillis() {
|
||||
return 654000; // FIXME
|
||||
}
|
||||
native public static long uptimeMillis();
|
||||
|
||||
/**
|
||||
* Returns milliseconds since boot, including time spent in sleep.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -37,7 +38,7 @@ void ALooper_release(ALooper* looper) {
|
||||
_ZNK7android7RefBase9decStrongEPKv(looper, (void*)ALooper_acquire);
|
||||
}
|
||||
|
||||
int _ZN7android6Looper7pollAllEiPiS1_PPv(ALooper *this, int timeoutMillis, int* outFd, int* outEvents, void** outData);
|
||||
int _ZN7android6Looper7pollAllEiPiS1_PPv(ALooper *this, int timeoutMillis, int *outFd, int *outEvents, void **outData);
|
||||
int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
|
||||
{
|
||||
ALooper *looper = ALooper_forThread();
|
||||
@@ -49,12 +50,34 @@ int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outDat
|
||||
return _ZN7android6Looper7pollAllEiPiS1_PPv(looper, timeoutMillis, outFd, outEvents, outData);
|
||||
}
|
||||
|
||||
int _ZN7android6Looper5addFdEiiiPFiiiPvES1_(ALooper *this, int fd, int ident, int events, Looper_callbackFunc callback, void* data);
|
||||
int _ZN7android6Looper8pollOnceEiPiS1_PPv(ALooper *this, int timeoutMillis, int *outFd, int *outEvents, void **outData);
|
||||
int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData)
|
||||
{
|
||||
ALooper *looper = ALooper_forThread();
|
||||
if(!looper) {
|
||||
fprintf(stderr, "ALooper_pollAll: ALooper_forThread returned NULL\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ZN7android6Looper8pollOnceEiPiS1_PPv(looper, timeoutMillis, outFd, outEvents, outData);
|
||||
}
|
||||
|
||||
int _ZN7android6Looper5addFdEiiiPFiiiPvES1_(ALooper *this, int fd, int ident, int events, Looper_callbackFunc callback, void *data);
|
||||
int ALooper_addFd(ALooper* looper, int fd, int ident, int events, Looper_callbackFunc callback, void* data)
|
||||
{
|
||||
return _ZN7android6Looper5addFdEiiiPFiiiPvES1_(looper, fd, ident, events, callback, data);
|
||||
}
|
||||
|
||||
void _ZN7android6Looper4wakeEv(ALooper *this);
|
||||
void ALooper_wake(ALooper* looper) {
|
||||
void ALooper_wake(ALooper *looper)
|
||||
{
|
||||
_ZN7android6Looper4wakeEv(looper);
|
||||
}
|
||||
|
||||
/* this is not part of the android API, but we use it internally */
|
||||
|
||||
bool _ZNK7android6Looper9isPollingEv(ALooper *this);
|
||||
bool ALooper_isPolling(ALooper *looper)
|
||||
{
|
||||
return _ZNK7android6Looper9isPollingEv(looper);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user