api: threads, events

This commit is contained in:
hyb1996
2017-12-28 21:21:41 +08:00
parent 729958d419
commit 3647cef81b
13 changed files with 394 additions and 34 deletions

View File

@@ -0,0 +1,23 @@
auto();
threads.start(function(){
//在子线程中调用observeKey()从而使按键事件处理在子线程执行
events.observeKey();
events.on("key_down", function(keyCode, events){
//音量键关闭脚本
if(keyCode == keys.volume_up){
exit();
}
});
});
toast("音量上键关闭脚本");
events.on("exit", function(){
toast("脚本已结束");
});
while(true){
log("脚本运行中...");
sleep(2000);
}

View File

@@ -88,6 +88,13 @@ public class EditActivity extends BaseActivity implements OnActivityResultDelega
super.onActionModeStarted(mode); super.onActionModeStarted(mode);
} }
@Override
public void onBackPressed() {
if (!mEditor.onBackPressed()) {
super.onBackPressed();
}
}
@Override @Override
public void finish() { public void finish() {
if (mEditor.isTextChanged()) { if (mEditor.isTextChanged()) {

View File

@@ -91,7 +91,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
FunctionsKeyboardView mFunctionsKeyboard; FunctionsKeyboardView mFunctionsKeyboard;
@ViewById(R.id.docs) @ViewById(R.id.docs)
EWebView mEWebView; EWebView mDocsWebView;
@ViewById(R.id.drawer_layout) @ViewById(R.id.drawer_layout)
DrawerLayout mDrawerLayout; DrawerLayout mDrawerLayout;
@@ -201,8 +201,8 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
setUpInputMethodEnhancedBar(); setUpInputMethodEnhancedBar();
setUpFunctionsKeyboard(); setUpFunctionsKeyboard();
setMenuItemStatus(R.id.save, false); setMenuItemStatus(R.id.save, false);
mEWebView.getWebView().getSettings().setDisplayZoomControls(true); mDocsWebView.getWebView().getSettings().setDisplayZoomControls(true);
mEWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html"); mDocsWebView.getWebView().loadUrl(Pref.getDocumentationUrl() + "index.html");
} }
@@ -257,6 +257,18 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
mShowFunctionsButton.setColorFilter(textColor); mShowFunctionsButton.setColorFilter(textColor);
} }
public boolean onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.START)) {
if (mDocsWebView.getWebView().canGoBack()) {
mDocsWebView.getWebView().goBack();
} else {
mDrawerLayout.closeDrawer(Gravity.START);
}
return true;
}
return false;
}
@Click(R.id.run) @Click(R.id.run)
public void runAndSaveFileIfNeeded() { public void runAndSaveFileIfNeeded() {
@@ -414,7 +426,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
.title(title) .title(title)
.url(absUrl) .url(absUrl)
.pinToLeft(v -> { .pinToLeft(v -> {
mEWebView.getWebView().loadUrl(absUrl); mDocsWebView.getWebView().loadUrl(absUrl);
mDrawerLayout.openDrawer(Gravity.START); mDrawerLayout.openDrawer(Gravity.START);
}) })
.show(); .show();

View File

@@ -49,7 +49,6 @@ var __that__ = this;
var Promise = require('promise.js'); var Promise = require('promise.js');
var JSON = require('__json2__.js'); var JSON = require('__json2__.js');
var util = require('__util__.js'); var util = require('__util__.js');
var threads = __runtime__.threads;
var device = __runtime__.device; var device = __runtime__.device;
var __asGlobal__ = function(obj, functions){ var __asGlobal__ = function(obj, functions){
@@ -65,7 +64,7 @@ require("__general__")(__runtime__, this);
(function(scope){ (function(scope){
var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui', var modules = ['app', 'automator', 'console', 'dialogs', 'io', 'selector', 'shell', 'web', 'ui',
"images", "timers", "events", "engines", "RootAutomator", "http", "storages", "floaty"]; "images", "timers", "threads", "events", "engines", "RootAutomator", "http", "storages", "floaty"];
var len = modules.length; var len = modules.length;
for(var i = 0; i < len; i++) { for(var i = 0; i < len; i++) {
var m = modules[i]; var m = modules[i];

View File

@@ -0,0 +1,12 @@
module.exports = function(__runtime__, scope){
var threads = Object.create(__runtime__.threads);
scope.sync = function(func, lock){
lock = lock || null;
return new org.mozilla.javascript.Synchronizer(func, lock);
}
return threads;
}

View File

@@ -3,6 +3,7 @@ package com.stardust.autojs.core.eventloop;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.stardust.autojs.core.looper.Timer;
import com.stardust.autojs.runtime.ScriptBridges; import com.stardust.autojs.runtime.ScriptBridges;
import com.stardust.autojs.runtime.exception.ScriptException; import com.stardust.autojs.runtime.exception.ScriptException;
@@ -19,6 +20,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class EventEmitter { public class EventEmitter {
private static class ListenerWrapper { private static class ListenerWrapper {
Object listener; Object listener;
boolean isOnce; boolean isOnce;
@@ -52,7 +54,11 @@ public class EventEmitter {
Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator(); Iterator<ListenerWrapper> listenerIterator = mListenerWrappers.iterator();
while (listenerIterator.hasNext()) { while (listenerIterator.hasNext()) {
ListenerWrapper listenerWrapper = listenerIterator.next(); ListenerWrapper listenerWrapper = listenerIterator.next();
mBridges.callFunction(listenerWrapper.listener, EventEmitter.this, args); if (mTimer != null) {
mTimer.setImmediate(listenerWrapper.listener, args);
} else {
mBridges.callFunction(listenerWrapper.listener, EventEmitter.this, args);
}
if (listenerWrapper.isOnce) { if (listenerWrapper.isOnce) {
listenerIterator.remove(); listenerIterator.remove();
} }
@@ -93,11 +99,17 @@ public class EventEmitter {
public static int defaultMaxListeners = 10; public static int defaultMaxListeners = 10;
private int mMaxListeners = defaultMaxListeners; private int mMaxListeners = defaultMaxListeners;
protected ScriptBridges mBridges; protected ScriptBridges mBridges;
private Timer mTimer;
public EventEmitter(ScriptBridges bridges) { public EventEmitter(ScriptBridges bridges) {
mBridges = bridges; mBridges = bridges;
} }
public EventEmitter(ScriptBridges bridges, Timer timer) {
mTimer = timer;
mBridges = bridges;
}
public EventEmitter once(String eventName, Object listener) { public EventEmitter once(String eventName, Object listener) {
getListeners(eventName).add(listener, true); getListeners(eventName).add(listener, true);
return this; return this;

View File

@@ -0,0 +1,225 @@
package com.stardust.autojs.core.looper;
import android.content.pm.PackageManager;
import com.stardust.autojs.runtime.ScriptRuntime;
import java.util.Map;
/**
* Created by Stardust on 2017/12/28.
*/
public class MainThreadProxy {
private final Thread mThread;
private ScriptRuntime mRuntime;
public MainThreadProxy(Thread thread, ScriptRuntime runtime) {
mThread = thread;
mRuntime = runtime;
}
public int setTimeout(Object callback, long delay, Object... args) {
return getMainTimer().setTimeout(callback, delay, args);
}
private Timer getMainTimer() {
return mRuntime.timers.getMainTimer();
}
public boolean clearTimeout(int id) {
return getMainTimer().clearTimeout(id);
}
public int setInterval(Object listener, long interval, Object... args) {
return getMainTimer().setInterval(listener, interval, args);
}
public boolean clearInterval(int id) {
return getMainTimer().clearInterval(id);
}
public int setImmediate(Object listener, Object... args) {
return getMainTimer().setImmediate(listener, args);
}
public boolean clearImmediate(int id) {
return getMainTimer().clearImmediate(id);
}
public static Thread currentThread() {
return Thread.currentThread();
}
public static void yield() {
Thread.yield();
}
public static void sleep(long millis) throws InterruptedException {
Thread.sleep(millis);
}
public static void sleep(long millis, int nanos) throws InterruptedException {
Thread.sleep(millis, nanos);
}
public void start() {
mThread.start();
}
public void run() {
mThread.run();
}
@Deprecated
public void stop() {
mThread.stop();
}
@Deprecated
public void stop(Throwable obj) {
mThread.stop(obj);
}
public void interrupt() {
mThread.interrupt();
}
public static boolean interrupted() {
return Thread.interrupted();
}
public boolean isInterrupted() {
return mThread.isInterrupted();
}
@Deprecated
public void destroy() {
mThread.destroy();
}
public boolean isAlive() {
return mThread.isAlive();
}
@Deprecated
public void suspend() {
mThread.suspend();
}
@Deprecated
public void resume() {
mThread.resume();
}
public void setPriority(int newPriority) {
mThread.setPriority(newPriority);
}
public int getPriority() {
return mThread.getPriority();
}
public void setName(String name) {
mThread.setName(name);
}
public String getName() {
return mThread.getName();
}
public ThreadGroup getThreadGroup() {
return mThread.getThreadGroup();
}
public static int activeCount() {
return Thread.activeCount();
}
public static int enumerate(Thread[] tarray) {
return Thread.enumerate(tarray);
}
@Deprecated
public int countStackFrames() {
return mThread.countStackFrames();
}
public void join(long millis) throws InterruptedException {
mThread.join(millis);
}
public void join(long millis, int nanos) throws InterruptedException {
mThread.join(millis, nanos);
}
public void join() throws InterruptedException {
mThread.join();
}
public static void dumpStack() {
Thread.dumpStack();
}
public void setDaemon(boolean on) {
mThread.setDaemon(on);
}
public boolean isDaemon() {
return mThread.isDaemon();
}
public void checkAccess() {
mThread.checkAccess();
}
public ClassLoader getContextClassLoader() {
return mThread.getContextClassLoader();
}
public void setContextClassLoader(ClassLoader cl) {
mThread.setContextClassLoader(cl);
}
public static boolean holdsLock(Object obj) {
return Thread.holdsLock(obj);
}
public StackTraceElement[] getStackTrace() {
return mThread.getStackTrace();
}
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
return Thread.getAllStackTraces();
}
public long getId() {
return mThread.getId();
}
public Thread.State getState() {
return mThread.getState();
}
@Override
public String toString() {
return mThread.toString();
}
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {
Thread.setDefaultUncaughtExceptionHandler(eh);
}
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return Thread.getDefaultUncaughtExceptionHandler();
}
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
return mThread.getUncaughtExceptionHandler();
}
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {
mThread.setUncaughtExceptionHandler(eh);
}
}

View File

@@ -109,4 +109,5 @@ public class Timer {
Log.d(LOG_TAG, "mMaxCallbackUptimeMillisForAllThreads:" + mMaxCallbackUptimeMillis); Log.d(LOG_TAG, "mMaxCallbackUptimeMillisForAllThreads:" + mMaxCallbackUptimeMillis);
return mMaxCallbackUptimeMillis > SystemClock.uptimeMillis(); return mMaxCallbackUptimeMillis > SystemClock.uptimeMillis();
} }
} }

View File

@@ -11,6 +11,8 @@ import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.concurrent.VolatileBox; import com.stardust.concurrent.VolatileBox;
import com.stardust.lang.ThreadCompat; import com.stardust.lang.ThreadCompat;
import org.mozilla.javascript.NativeArray;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@@ -25,6 +27,8 @@ public class TimerThread extends ThreadCompat {
private final VolatileBox<Long> mMaxCallbackUptimeMillisForAllThreads; private final VolatileBox<Long> mMaxCallbackUptimeMillisForAllThreads;
private final ScriptRuntime mRuntime; private final ScriptRuntime mRuntime;
private Runnable mTarget; private Runnable mTarget;
private boolean mRunning = false;
private final Object mRunningLock = new Object();
public TimerThread(ScriptRuntime runtime, VolatileBox<Long> maxCallbackUptimeMillisForAllThreads, Runnable target) { public TimerThread(ScriptRuntime runtime, VolatileBox<Long> maxCallbackUptimeMillisForAllThreads, Runnable target) {
super(target); super(target);
@@ -38,6 +42,7 @@ public class TimerThread extends ThreadCompat {
mRuntime.loopers.prepare(); mRuntime.loopers.prepare();
mTimer = new Timer(mRuntime.bridges, mMaxCallbackUptimeMillisForAllThreads); mTimer = new Timer(mRuntime.bridges, mMaxCallbackUptimeMillisForAllThreads);
sTimerMap.put(Thread.currentThread(), mTimer); sTimerMap.put(Thread.currentThread(), mTimer);
notifyRunning();
new Handler().post(mTarget); new Handler().post(mTarget);
try { try {
Looper.loop(); Looper.loop();
@@ -47,10 +52,18 @@ public class TimerThread extends ThreadCompat {
} }
} finally { } finally {
onExit(); onExit();
mTimer = null;
sTimerMap.remove(Thread.currentThread(), mTimer); sTimerMap.remove(Thread.currentThread(), mTimer);
} }
} }
private void notifyRunning() {
synchronized (mRunningLock) {
mRunning = true;
mRunningLock.notifyAll();
}
}
@CallSuper @CallSuper
protected void onExit() { protected void onExit() {
mRuntime.loopers.notifyThreadExit(this); mRuntime.loopers.notifyThreadExit(this);
@@ -65,26 +78,46 @@ public class TimerThread extends ThreadCompat {
} }
public int setTimeout(Object callback, long delay, Object... args) { public int setTimeout(Object callback, long delay, Object... args) {
return mTimer.setTimeout(callback, delay, args); return getTimer().setTimeout(callback, delay, args);
}
private Timer getTimer() {
if (mTimer == null) {
throw new IllegalStateException("thread is not alive");
}
return mTimer;
} }
public boolean clearTimeout(int id) { public boolean clearTimeout(int id) {
return mTimer.clearTimeout(id); return getTimer().clearTimeout(id);
} }
public int setInterval(Object listener, long interval, Object... args) { public int setInterval(Object listener, long interval, Object... args) {
return mTimer.setInterval(listener, interval, args); return getTimer().setInterval(listener, interval, args);
} }
public boolean clearInterval(int id) { public boolean clearInterval(int id) {
return mTimer.clearInterval(id); return getTimer().clearInterval(id);
} }
public int setImmediate(Object listener, Object... args) { public int setImmediate(Object listener, Object... args) {
return mTimer.setImmediate(listener, args); return getTimer().setImmediate(listener, args);
} }
public boolean clearImmediate(int id) { public boolean clearImmediate(int id) {
return mTimer.clearImmediate(id); return getTimer().clearImmediate(id);
}
public void waitFor() throws InterruptedException {
synchronized (mRunningLock) {
if (mRunning)
return;
mRunningLock.wait();
}
}
@Override
public String toString() {
return "Thread[" + getName() + "," + getPriority() + "]";
} }
} }

View File

@@ -153,7 +153,7 @@ public class ScriptRuntime {
public final Engines engines; public final Engines engines;
@ScriptVariable @ScriptVariable
public final Threads threads; public Threads threads;
@ScriptVariable @ScriptVariable
public final Floaty floaty; public final Floaty floaty;
@@ -187,7 +187,6 @@ public class ScriptRuntime {
} }
engines = new Engines(builder.mEngineService); engines = new Engines(builder.mEngineService);
dialogs = new Dialogs(app, uiHandler, bridges); dialogs = new Dialogs(app, uiHandler, bridges);
threads = new Threads(this);
device = new Device(uiHandler.getContext()); device = new Device(uiHandler.getContext());
floaty = new Floaty(uiHandler, ui); floaty = new Floaty(uiHandler, ui);
} }
@@ -195,7 +194,8 @@ public class ScriptRuntime {
public void init() { public void init() {
if (loopers != null) if (loopers != null)
throw new IllegalStateException("already initialized"); throw new IllegalStateException("already initialized");
timers = new Timers(bridges); threads = new Threads(this);
timers = new Timers(bridges, threads);
loopers = new Loopers(this); loopers = new Loopers(this);
events = new Events(uiHandler.getContext(), accessibilityBridge, this); events = new Events(uiHandler.getContext(), accessibilityBridge, this);
mThread = Thread.currentThread(); mThread = Thread.currentThread();

View File

@@ -14,6 +14,8 @@ import com.stardust.autojs.R;
import com.stardust.autojs.core.accessibility.AccessibilityBridge; import com.stardust.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.eventloop.EventEmitter; import com.stardust.autojs.core.eventloop.EventEmitter;
import com.stardust.autojs.core.looper.Loopers; import com.stardust.autojs.core.looper.Loopers;
import com.stardust.autojs.core.looper.MainThreadProxy;
import com.stardust.autojs.core.looper.Timer;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
import com.stardust.notification.Notification; import com.stardust.notification.Notification;
import com.stardust.notification.NotificationListenerService; import com.stardust.notification.NotificationListenerService;
@@ -58,6 +60,15 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver
return new EventEmitter(mBridges); return new EventEmitter(mBridges);
} }
public EventEmitter emitter(Thread thread) {
Timer timer = mScriptRuntime.timers.getTimerForThread(thread);
return new EventEmitter(mBridges, timer);
}
public EventEmitter emitter(MainThreadProxy mainThreadProxy) {
return new EventEmitter(mBridges, mScriptRuntime.timers.getMainTimer());
}
public void observeKey() { public void observeKey() {
if (mListeningKey) if (mListeningKey)
return; return;

View File

@@ -2,6 +2,7 @@ package com.stardust.autojs.runtime.api;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.stardust.autojs.core.looper.MainThreadProxy;
import com.stardust.autojs.core.looper.TimerThread; import com.stardust.autojs.core.looper.TimerThread;
import com.stardust.autojs.engine.RhinoJavaScriptEngine; import com.stardust.autojs.engine.RhinoJavaScriptEngine;
import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.ScriptRuntime;
@@ -14,10 +15,15 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* Created by Stardust on 2017/12/3. * Created by Stardust on 2017/12/3.
@@ -27,15 +33,33 @@ public class Threads {
private final HashSet<Thread> mThreads = new HashSet<>(); private final HashSet<Thread> mThreads = new HashSet<>();
private ScriptRuntime mRuntime; private ScriptRuntime mRuntime;
private final Thread mMainThread;
private MainThreadProxy mMainThreadProxy;
private int mSpawnCount = 0;
public Threads(ScriptRuntime runtime) { public Threads(ScriptRuntime runtime) {
mRuntime = runtime; mRuntime = runtime;
mMainThread = Thread.currentThread();
mMainThreadProxy = new MainThreadProxy(Thread.currentThread(), mRuntime);
}
public Thread getMainThread() {
return mMainThread;
}
public Object currentThread() {
Thread thread = Thread.currentThread();
if (thread == mMainThread)
return mMainThreadProxy;
return thread;
} }
public TimerThread start(Runnable runnable) { public TimerThread start(Runnable runnable) {
TimerThread thread = startThread(runnable); TimerThread thread = startThread(runnable);
synchronized (mThreads) { synchronized (mThreads) {
mThreads.add(thread); mThreads.add(thread);
thread.setName(thread.getName() + " (Spawn-" + mSpawnCount + ")");
mSpawnCount++;
} }
thread.start(); thread.start();
return thread; return thread;
@@ -63,24 +87,16 @@ public class Threads {
return new VolatileDispose(); return new VolatileDispose();
} }
public List list() { public AtomicLong atomic(long value) {
return Collections.synchronizedList(new ArrayList<>()); return new AtomicLong(value);
}
public Set set() {
return new ConcurrentSkipListSet();
}
public Map map() {
return new ConcurrentHashMap();
} }
public AtomicLong atomic() { public AtomicLong atomic() {
return new AtomicLong(); return new AtomicLong();
} }
public AtomicLong atomic(long value) { public Lock lock() {
return new AtomicLong(value); return new ReentrantLock();
} }
public void shutDownAll() { public void shutDownAll() {

View File

@@ -19,12 +19,17 @@ public class Timers {
private static final String LOG_TAG = "Timers"; private static final String LOG_TAG = "Timers";
private VolatileBox<Long> mMaxCallbackUptimeMillisForAllThreads = new VolatileBox<>(0L); private VolatileBox<Long> mMaxCallbackUptimeMillisForAllThreads = new VolatileBox<>(0L);
private Thread mMainThread; private Threads mThreads;
private Timer mMainTimer; private Timer mMainTimer;
public Timers(ScriptBridges bridges) {
mMainThread = Thread.currentThread(); public Timers(ScriptBridges bridges, Threads threads) {
mMainTimer = new Timer(bridges, mMaxCallbackUptimeMillisForAllThreads); mMainTimer = new Timer(bridges, mMaxCallbackUptimeMillisForAllThreads);
mThreads = threads;
}
public Timer getMainTimer() {
return mMainTimer;
} }
public VolatileBox<Long> getMaxCallbackUptimeMillisForAllThreads() { public VolatileBox<Long> getMaxCallbackUptimeMillisForAllThreads() {
@@ -32,10 +37,14 @@ public class Timers {
} }
private Timer getTimerForCurrentThread() { private Timer getTimerForCurrentThread() {
if (Thread.currentThread() == mMainThread) { return getTimerForThread(Thread.currentThread());
}
public Timer getTimerForThread(Thread thread) {
if (thread == mThreads.getMainThread()) {
return mMainTimer; return mMainTimer;
} }
return TimerThread.getTimerForCurrentThread(); return TimerThread.getTimerForThread(thread);
} }
public int setTimeout(Object callback, long delay, Object... args) { public int setTimeout(Object callback, long delay, Object... args) {
@@ -64,7 +73,7 @@ public class Timers {
public boolean hasPendingCallbacks() { public boolean hasPendingCallbacks() {
//如果是脚本主线程,则检查所有子线程中的定时回调。mFutureCallbackUptimeMillis用来记录所有子线程中定时最久的一个。 //如果是脚本主线程,则检查所有子线程中的定时回调。mFutureCallbackUptimeMillis用来记录所有子线程中定时最久的一个。
if (mMainThread == Thread.currentThread()) { if (mThreads.getMainThread() == Thread.currentThread()) {
Log.d(LOG_TAG, "[main thread]hasPendingCallbacks:" + (mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis())); Log.d(LOG_TAG, "[main thread]hasPendingCallbacks:" + (mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis()));
Log.d(LOG_TAG, "mMaxCallbackUptimeMillisForAllThreads:" + mMaxCallbackUptimeMillisForAllThreads.get()); Log.d(LOG_TAG, "mMaxCallbackUptimeMillisForAllThreads:" + mMaxCallbackUptimeMillisForAllThreads.get());
return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis(); return mMaxCallbackUptimeMillisForAllThreads.get() > SystemClock.uptimeMillis();