api: threads, events
This commit is contained in:
23
app/src/main/assets/sample/多线程/多线程按键监听.js
Normal file
23
app/src/main/assets/sample/多线程/多线程按键监听.js
Normal 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);
|
||||||
|
}
|
||||||
@@ -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()) {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
12
autojs/src/main/assets/modules/__threads__.js
Normal file
12
autojs/src/main/assets/modules/__threads__.js
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user