Attempt to fix selector memeory leak. Add update checker
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
if(__engine__ == "rhino"){
|
||||
if(__engine_name__ == "rhino"){
|
||||
__importClassOld__ = importClass;
|
||||
var importClass = function(pack){
|
||||
if(typeof(pack) == "string"){
|
||||
@@ -167,9 +167,9 @@ var scrollDown = function(a, b, c, d){
|
||||
|
||||
var input = function(a, b){
|
||||
if(arguments.length == 1){
|
||||
return __runtime__.automator.setText(__runtime__.editable(-1), a);
|
||||
return __runtime__.automator.setText(__runtime__.automator.editable(-1), a);
|
||||
}else{
|
||||
return __runtime__.automator.setText(__runtime__.editable(a), b);
|
||||
return __runtime__.automator.setText(__runtime__.automator.editable(a), b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,14 +246,18 @@ var Text = function(text){
|
||||
return shell("input text " + text, true).code == 1;
|
||||
}
|
||||
|
||||
var __selector__ = __runtime__.selector();
|
||||
var selector = function(){
|
||||
return __runtime__.selector(__engine__);
|
||||
}
|
||||
|
||||
var __selector__ = selector();
|
||||
var __obj__ = new java.lang.Object();
|
||||
|
||||
for(var x in __selector__){
|
||||
if(!__obj__[x] && !this[x]){
|
||||
this[x] = (function(method) {
|
||||
return function(){
|
||||
var s = __runtime__.selector();
|
||||
var s = selector();
|
||||
//这里不知道怎么写。尴尬。只能写成这样。
|
||||
if(arguments.length == 0){
|
||||
return s[method]();
|
||||
@@ -274,8 +278,16 @@ for(var x in __selector__){
|
||||
|
||||
}
|
||||
|
||||
var open = function(path, mode){
|
||||
return com.stardust.pio.PFile.open(path, mode);
|
||||
var open = function(path, mode, encoding, bufferSize){
|
||||
if(arguments.length == 1){
|
||||
return com.stardust.pio.PFile.open(path);
|
||||
}else if(arguments.length == 2){
|
||||
return com.stardust.pio.PFile.open(path, mode);
|
||||
}else if(arguments.length == 3){
|
||||
return com.stardust.pio.PFile.open(path, mode, encoding);
|
||||
}else if(arguments.length == 4){
|
||||
return com.stardust.pio.PFile.open(path, mode, encoding, bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
__importClassOld__(com.stardust.autojs.runtime.api.Shell);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.stardust.autojs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.JavaScriptEngineManager;
|
||||
@@ -10,6 +11,7 @@ import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -20,6 +22,7 @@ import java.util.Set;
|
||||
|
||||
public class ScriptEngineService {
|
||||
|
||||
private static final String LOG_TAG = "ScriptEngineService";
|
||||
private static ScriptEngineService instance;
|
||||
|
||||
public static ScriptEngineService getInstance() {
|
||||
@@ -73,7 +76,9 @@ public class ScriptEngineService {
|
||||
}
|
||||
|
||||
public JavaScriptEngine createScriptEngine() {
|
||||
return mJavaScriptEngineManager.createEngine();
|
||||
JavaScriptEngine engine = mJavaScriptEngineManager.createEngine();
|
||||
Log.i(LOG_TAG, Arrays.toString(Thread.currentThread().getStackTrace()));
|
||||
return engine;
|
||||
}
|
||||
|
||||
public void registerEngineLifecycleCallback(JavaScriptEngineManager.EngineLifecycleCallback engineLifecycleCallback) {
|
||||
|
||||
@@ -40,6 +40,7 @@ public class ScriptExecutionTask implements Serializable {
|
||||
runtime.ensureAccessibilityServiceEnabled();
|
||||
}
|
||||
mExecutionListener.onStart(engine, mScriptSource);
|
||||
engine.setTag("script", mScriptSource);
|
||||
mExecutionListener.onSuccess(engine, mScriptSource, engine.execute(mScriptSource));
|
||||
} catch (Exception e) {
|
||||
mExecutionListener.onException(engine, mScriptSource, e);
|
||||
|
||||
@@ -21,12 +21,14 @@ public interface JavaScriptEngine {
|
||||
|
||||
Object execute(ScriptSource scriptSource);
|
||||
|
||||
ScriptSource getExecutedScript();
|
||||
|
||||
void forceStop();
|
||||
|
||||
void destroy();
|
||||
|
||||
void setTag(String key, Object value);
|
||||
|
||||
Object getTag(String key);
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -44,13 +44,17 @@ public abstract class JavaScriptEngineManager {
|
||||
JavaScriptEngine engine = createEngineInner();
|
||||
putProperties(engine);
|
||||
engine.init();
|
||||
addEngine(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
private void addEngine(JavaScriptEngine engine) {
|
||||
synchronized (mEngines) {
|
||||
mEngines.add(engine);
|
||||
if(mEngineLifecycleCallback != null){
|
||||
if (mEngineLifecycleCallback != null) {
|
||||
mEngineLifecycleCallback.onEngineCreate(engine);
|
||||
}
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
public void put(String varName, Object value) {
|
||||
@@ -82,7 +86,7 @@ public abstract class JavaScriptEngineManager {
|
||||
void removeEngine(JavaScriptEngine engine) {
|
||||
synchronized (mEngines) {
|
||||
mEngines.remove(engine);
|
||||
if(mEngineLifecycleCallback != null){
|
||||
if (mEngineLifecycleCallback != null) {
|
||||
mEngineLifecycleCallback.onEngineRemove(engine);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package com.stardust.autojs.engine;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.rhino_android.AndroidContextFactory;
|
||||
import com.stardust.autojs.rhino_android.RhinoAndroidHelper;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.runtime.ScriptStopException;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
@@ -12,6 +16,12 @@ import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -19,17 +29,20 @@ import java.io.File;
|
||||
|
||||
public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
private static final String LOG_TAG = "RhinoJavaScriptEngine";
|
||||
|
||||
private Context mContext;
|
||||
private Scriptable mScriptable;
|
||||
private Thread mThread;
|
||||
private RhinoJavaScriptEngineManager mEngineManager;
|
||||
private ScriptSource mScriptSource;
|
||||
private Map<String, Object> mTags = new Hashtable<>();
|
||||
|
||||
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) {
|
||||
mEngineManager = engineManager;
|
||||
mThread = Thread.currentThread();
|
||||
mContext = createContext();
|
||||
mScriptable = createScope(mContext);
|
||||
setTag("create-traces", Arrays.toString(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,15 +52,11 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
@Override
|
||||
public Object execute(ScriptSource source) {
|
||||
mScriptSource = source;
|
||||
setTag("execute-traces", Arrays.toString(Thread.currentThread().getStackTrace()));
|
||||
setTag("execute-source", source);
|
||||
return mContext.evaluateString(mScriptable, source.getScript(), "<script>", 1, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptSource getExecutedScript() {
|
||||
return mScriptSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceStop() {
|
||||
mThread.interrupt();
|
||||
@@ -60,12 +69,37 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
@Override
|
||||
public void destroy() {
|
||||
Context.exit();
|
||||
// TODO: 2017/4/6 XXX :在这里回收内存池并不好
|
||||
final AccessibilityNodeInfoAllocator allocator = (AccessibilityNodeInfoAllocator) getTag("allocator");
|
||||
if (allocator != null) {
|
||||
new Timer().schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
//allocator.recycleAll();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
mEngineManager.removeEngine(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTag(String key, Object value) {
|
||||
mTags.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object getTag(String key) {
|
||||
Object tag = mTags.get(key);
|
||||
if (tag == null && key.equals("script")) {
|
||||
Log.i(LOG_TAG, mTags.entrySet().toString());
|
||||
}
|
||||
return mTags.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
ScriptableObject.putProperty(mScriptable, "__engine__", "rhino");
|
||||
ScriptableObject.putProperty(mScriptable, "__engine_name__", "rhino");
|
||||
ScriptableObject.putProperty(mScriptable, "__engine__", this);
|
||||
mContext.evaluateString(mScriptable, mEngineManager.getInitScript().getScript(), "<init>", 1, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ public class RhinoJavaScriptEngineManager extends JavaScriptEngineManager {
|
||||
|
||||
private String mRequirePath = "";
|
||||
|
||||
|
||||
public RhinoJavaScriptEngineManager(android.content.Context context, ScriptRuntime runtime) {
|
||||
super(context);
|
||||
put("__runtime__", runtime);
|
||||
@@ -65,7 +66,9 @@ public class RhinoJavaScriptEngineManager extends JavaScriptEngineManager {
|
||||
|
||||
private String[] getGlobalFunctionsInner() {
|
||||
JavaScriptEngine engine = createEngine();
|
||||
Scriptable scriptable = (Scriptable) engine.execute(new StringScriptSource("this"));
|
||||
ScriptSource source = new StringScriptSource("this", "this");
|
||||
engine.setTag("script", source);
|
||||
Scriptable scriptable = (Scriptable) engine.execute(source);
|
||||
Object[] ids = scriptable.getIds();
|
||||
String[] functions = new String[ids.length];
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
|
||||
@@ -46,6 +46,7 @@ public class ScriptExecuteActivity extends Activity {
|
||||
private void runScript() {
|
||||
mJavaScriptEngine.put("activity", this);
|
||||
try {
|
||||
mJavaScriptEngine.setTag("script", mScriptSource);
|
||||
mResult = mJavaScriptEngine.execute(mScriptSource);
|
||||
} catch (Exception e) {
|
||||
mExecutionListener.onException(mJavaScriptEngine, mScriptSource, e);
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.os.Handler;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.rhino_android.AndroidClassLoader;
|
||||
import com.stardust.autojs.runtime.simple_action.SimpleActionAutomator;
|
||||
import com.stardust.autojs.runtime.api.AppUtils;
|
||||
@@ -16,6 +17,7 @@ import com.stardust.util.ClipboardUtil;
|
||||
import com.stardust.util.SdkVersionUtil;
|
||||
import com.stardust.util.Shell;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
|
||||
@@ -92,8 +94,13 @@ public class ScriptRuntime {
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public UiSelector selector() {
|
||||
return new UiSelector(mAccessibilityBridge);
|
||||
public UiSelector selector(JavaScriptEngine engine) {
|
||||
AccessibilityNodeInfoAllocator allocator = (AccessibilityNodeInfoAllocator) engine.getTag("allocator");
|
||||
if(allocator == null){
|
||||
allocator = new AccessibilityNodeInfoAllocator();
|
||||
engine.setTag("allocator", allocator);
|
||||
}
|
||||
return new UiSelector(mAccessibilityBridge, allocator);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
|
||||
@@ -7,12 +7,14 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.autojs.runtime.AccessibilityBridge;
|
||||
import com.stardust.autojs.runtime.JavascriptInterface;
|
||||
import com.stardust.autojs.runtime.ScriptStopException;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.automator.ActionArgument;
|
||||
import com.stardust.automator.UiGlobalSelector;
|
||||
import com.stardust.automator.UiObject;
|
||||
import com.stardust.automator.UiObjectCollection;
|
||||
import com.stardust.automator.filter.DfsFilter;
|
||||
import com.stardust.util.DeveloperUtils;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
|
||||
@@ -53,6 +55,7 @@ import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.
|
||||
|
||||
public class UiSelector extends UiGlobalSelector {
|
||||
|
||||
@Deprecated
|
||||
private class FindCommand extends AccessibilityEventCommandHost.AbstractCommand {
|
||||
|
||||
UiObjectCollection result;
|
||||
@@ -70,20 +73,28 @@ public class UiSelector extends UiGlobalSelector {
|
||||
private static final String TAG = "UiSelector";
|
||||
|
||||
private AccessibilityBridge mAccessibilityBridge;
|
||||
private AccessibilityNodeInfoAllocator mAllocator = AccessibilityNodeInfoAllocator.getGlobal();
|
||||
|
||||
public UiSelector(AccessibilityBridge accessibilityBridge) {
|
||||
mAccessibilityBridge = accessibilityBridge;
|
||||
}
|
||||
|
||||
public UiSelector(AccessibilityBridge accessibilityBridge, AccessibilityNodeInfoAllocator allocator) {
|
||||
mAccessibilityBridge = accessibilityBridge;
|
||||
mAllocator = allocator;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public UiObjectCollection find() {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
if (isRunningPackageSelf()) {
|
||||
return null;
|
||||
}
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
if (service != null) {
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root != null) {
|
||||
return findOf(root);
|
||||
return findOf(mAllocator, root);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -93,12 +104,19 @@ public class UiSelector extends UiGlobalSelector {
|
||||
mAccessibilityBridge.ensureServiceEnabled();
|
||||
}
|
||||
|
||||
private boolean isRunningPackageSelf() {
|
||||
return DeveloperUtils.isRunningPackageSelf(mAccessibilityBridge.getInfoProvider().getLatestPackage());
|
||||
}
|
||||
|
||||
|
||||
@JavascriptInterface
|
||||
@NonNull
|
||||
public UiObjectCollection untilFind() {
|
||||
UiObjectCollection uiObjectCollection;
|
||||
do {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new ScriptStopException(new InterruptedException());
|
||||
}
|
||||
uiObjectCollection = find();
|
||||
} while (uiObjectCollection == null || uiObjectCollection.size() == 0);
|
||||
return uiObjectCollection;
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.automator.simple_action.SimpleAction;
|
||||
import com.stardust.automator.simple_action.ActionFactory;
|
||||
import com.stardust.automator.simple_action.ActionTarget;
|
||||
import com.stardust.util.DeveloperUtils;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -180,16 +182,26 @@ public class SimpleActionAutomator {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T performAction(SimpleAction simpleAction) {
|
||||
private boolean performAction(SimpleAction simpleAction) {
|
||||
ensureAccessibilityServiceEnabled();
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
if (service != null) {
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
Log.i("Automator", "performAction: " + simpleAction + " root = " + root);
|
||||
if (root != null) {
|
||||
simpleAction.setResult(simpleAction.perform(root));
|
||||
}
|
||||
if (isRunningPackageSelf()) {
|
||||
return false;
|
||||
}
|
||||
return (T) simpleAction.getResult();
|
||||
AccessibilityService service = mAccessibilityBridge.getService();
|
||||
if (service == null)
|
||||
return false;
|
||||
AccessibilityNodeInfo root = service.getRootInActiveWindow();
|
||||
if (root == null)
|
||||
return false;
|
||||
AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator();
|
||||
simpleAction.setAllocator(allocator);
|
||||
Log.i("Automator", "performAction: " + simpleAction + " root = " + root);
|
||||
boolean result = simpleAction.perform(root);
|
||||
allocator.recycleAll();
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isRunningPackageSelf() {
|
||||
return DeveloperUtils.isRunningPackageSelf(mAccessibilityBridge.getInfoProvider().getLatestPackage());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user