diff --git a/app/src/main/java/org/autojs/autojs/App.java b/app/src/main/java/org/autojs/autojs/App.java index dabe48ab..b6335a4d 100644 --- a/app/src/main/java/org/autojs/autojs/App.java +++ b/app/src/main/java/org/autojs/autojs/App.java @@ -91,7 +91,7 @@ public class App extends MultiDexApplication { // You should not init your app in this process. return; } - LeakCanary.install(this); + //LeakCanary.install(this); } private void init() { diff --git a/autojs/src/main/java/com/stardust/autojs/AutoJs.java b/autojs/src/main/java/com/stardust/autojs/AutoJs.java index 2f95ba50..90f47f67 100644 --- a/autojs/src/main/java/com/stardust/autojs/AutoJs.java +++ b/autojs/src/main/java/com/stardust/autojs/AutoJs.java @@ -65,6 +65,7 @@ public abstract class AutoJs { mNotificationObserver = new AccessibilityNotificationObserver(mContext); mAccessibilityInfoProvider = new AccessibilityInfoProvider(mContext.getPackageManager()); mScriptEngineService = buildScriptEngineService(); + ScriptEngineService.setInstance(mScriptEngineService); init(); } diff --git a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java index 7201205f..129b85da 100644 --- a/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java +++ b/autojs/src/main/java/com/stardust/autojs/ScriptEngineService.java @@ -67,9 +67,7 @@ public class ScriptEngineService { } private void onFinish(ScriptExecution execution) { - if (execution.getEngine() instanceof JavaScriptEngine) { - ((JavaScriptEngine) execution.getEngine()).getRuntime().onExit(); - } + } @Override @@ -87,6 +85,7 @@ public class ScriptEngineService { }; + private static ScriptEngineService sInstance; private final Context mContext; private UiHandler mUiHandler; private final Console mGlobalConsole; @@ -211,6 +210,18 @@ public class ScriptEngineService { return mScriptExecutions.get(id); } + public static void setInstance(ScriptEngineService service) { + if (sInstance != null) { + throw new IllegalStateException(); + } + sInstance = service; + } + + public static ScriptEngineService getInstance() { + return sInstance; + } + + private static class EngineLifecycleObserver implements ScriptEngineManager.EngineLifecycleCallback { private final Set mEngineLifecycleCallbacks = new LinkedHashSet<>(); diff --git a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java index 203d4857..39a76b16 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java +++ b/autojs/src/main/java/com/stardust/autojs/core/looper/Loopers.java @@ -5,7 +5,6 @@ import android.os.Looper; import android.os.MessageQueue; import android.util.Log; -import com.android.dx.util.IntSet; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.api.Threads; import com.stardust.autojs.runtime.api.Timers; @@ -33,7 +32,7 @@ public class Loopers implements MessageQueue.IdleHandler { private volatile ThreadLocal waitWhenIdle = new ThreadLocal<>(); private volatile ThreadLocal> waitIds = new ThreadLocal<>(); private volatile ThreadLocal maxWaitId = new ThreadLocal<>(); - private volatile ThreadLocal> looperQuitHanders = new ThreadLocal<>(); + private volatile ThreadLocal> looperQuitHandlers = new ThreadLocal<>(); private volatile Looper mServantLooper; private Timers mTimers; private ScriptRuntime mScriptRuntime; @@ -58,17 +57,17 @@ public class Loopers implements MessageQueue.IdleHandler { return mMainLooper; } - public void addLooperQuiteHandler(LooperQuitHandler handler) { - CopyOnWriteArrayList handlers = looperQuitHanders.get(); + public void addLooperQuitHandler(LooperQuitHandler handler) { + CopyOnWriteArrayList handlers = looperQuitHandlers.get(); if (handlers == null) { handlers = new CopyOnWriteArrayList<>(); - looperQuitHanders.set(handlers); + looperQuitHandlers.set(handlers); } handlers.add(handler); } - public boolean removeLooperQuiteHandler(LooperQuitHandler handler) { - CopyOnWriteArrayList handlers = looperQuitHanders.get(); + public boolean removeLooperQuitHandler(LooperQuitHandler handler) { + CopyOnWriteArrayList handlers = looperQuitHandlers.get(); return handlers != null && handlers.remove(handler); } @@ -82,7 +81,7 @@ public class Loopers implements MessageQueue.IdleHandler { if (waitWhenIdle.get() || !waitIds.get().isEmpty()) { return false; } - CopyOnWriteArrayList handlers = looperQuitHanders.get(); + CopyOnWriteArrayList handlers = looperQuitHandlers.get(); if (handlers == null) { return true; } diff --git a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java index abd7022d..957d4c69 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/JavaScriptEngine.java @@ -45,6 +45,12 @@ public abstract class JavaScriptEngine extends ScriptEngine.AbstractScriptEngine return (ScriptSource) getTag(TAG_SOURCE); } + @Override + public synchronized void destroy() { + mRuntime.onExit(); + super.destroy(); + } + @Override public String toString() { return "ScriptEngine@" + Integer.toHexString(hashCode()) + "{" + diff --git a/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java index f0a2c09a..dca86616 100644 --- a/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java +++ b/autojs/src/main/java/com/stardust/autojs/engine/ScriptEngine.java @@ -5,6 +5,7 @@ import android.support.annotation.CallSuper; import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.script.ScriptSource; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; @@ -68,7 +69,7 @@ public interface ScriptEngine { abstract class AbstractScriptEngine implements ScriptEngine { - private Map mTags = new ConcurrentHashMap<>(); + private Map mTags = new HashMap<>(); private OnDestroyListener mOnDestroyListener; private boolean mDestroyed = false; private Exception mUncaughtException; @@ -76,9 +77,11 @@ public interface ScriptEngine { @Override public synchronized void setTag(String key, Object value) { - if (value == null) - return; - mTags.put(key, value); + if (value == null) { + mTags.remove(key); + } else { + mTags.put(key, value); + } } @Override diff --git a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java index e4f6fb94..cdfc3db3 100644 --- a/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java +++ b/autojs/src/main/java/com/stardust/autojs/execution/ScriptExecuteActivity.java @@ -7,11 +7,13 @@ import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; +import com.stardust.autojs.ScriptEngineService; import com.stardust.autojs.core.eventloop.EventEmitter; import com.stardust.autojs.core.eventloop.SimpleEvent; import com.stardust.autojs.engine.JavaScriptEngine; @@ -21,7 +23,6 @@ import com.stardust.autojs.engine.ScriptEngineManager; import com.stardust.autojs.runtime.ScriptRuntime; import com.stardust.autojs.runtime.api.UI; import com.stardust.autojs.script.ScriptSource; -import com.stardust.util.IntentExtras; import org.mozilla.javascript.NativeObject; @@ -32,13 +33,13 @@ import org.mozilla.javascript.NativeObject; public class ScriptExecuteActivity extends AppCompatActivity { - private static final String EXTRA_EXECUTION = ScriptExecuteActivity.class.getName() + ".execution"; + private static final String LOG_TAG = "ScriptExecuteActivity"; + private static final String EXTRA_EXECUTION_ID = ScriptExecuteActivity.class.getName() + ".execution_id"; private Object mResult; private ScriptEngine mScriptEngine; private ScriptExecutionListener mExecutionListener; private ScriptSource mScriptSource; private ActivityScriptExecution mScriptExecution; - private IntentExtras mIntentExtras; private ScriptRuntime mRuntime; @@ -47,10 +48,8 @@ public class ScriptExecuteActivity extends AppCompatActivity { public static ActivityScriptExecution execute(Context context, ScriptEngineManager manager, ScriptExecutionTask task) { ActivityScriptExecution execution = new ActivityScriptExecution(manager, task); Intent i = new Intent(context, ScriptExecuteActivity.class) + .putExtra(EXTRA_EXECUTION_ID, execution.getId()) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - IntentExtras.newExtras() - .put(EXTRA_EXECUTION, execution) - .putInIntent(i); context.startActivity(i); return execution; } @@ -59,36 +58,30 @@ public class ScriptExecuteActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mIntentExtras = readIntentExtras(savedInstanceState); - if (mIntentExtras == null || mIntentExtras.get(EXTRA_EXECUTION) == null) { - finish(); + int executionId = getIntent().getIntExtra(EXTRA_EXECUTION_ID, ScriptExecution.NO_ID); + if (executionId == ScriptExecution.NO_ID) { + super.finish(); return; } - mScriptExecution = mIntentExtras.get(EXTRA_EXECUTION); + ScriptExecution execution = ScriptEngineService.getInstance().getScriptExecution(executionId); + if (execution == null || !(execution instanceof ActivityScriptExecution)) { + super.finish(); + return; + } + mScriptExecution = (ActivityScriptExecution) execution; mScriptSource = mScriptExecution.getSource(); mScriptEngine = mScriptExecution.createEngine(this); mExecutionListener = mScriptExecution.getListener(); mRuntime = ((JavaScriptEngine) mScriptEngine).getRuntime(); mEventEmitter = new EventEmitter(mRuntime.bridges); runScript(); + emit("create", savedInstanceState); } public EventEmitter getEventEmitter() { return mEventEmitter; } - private IntentExtras readIntentExtras(Bundle savedInstanceState) { - IntentExtras extras = IntentExtras.fromIntentAndRelease(getIntent()); - if (extras == null && savedInstanceState != null) { - int id = savedInstanceState.getInt(IntentExtras.EXTRA_ID, -1); - if (id == -1) { - return null; - } - extras = IntentExtras.fromIdAndRelease(id); - } - return extras; - } - private void runScript() { try { prepare(); @@ -130,6 +123,10 @@ public class ScriptExecuteActivity extends AppCompatActivity { @Override public void finish() { + if (mScriptExecution == null || mExecutionListener == null) { + super.finish(); + return; + } Exception exception = mScriptEngine.getUncaughtException(); if (exception != null) { onException(exception); @@ -142,6 +139,7 @@ public class ScriptExecuteActivity extends AppCompatActivity { @Override protected void onDestroy() { super.onDestroy(); + Log.d(LOG_TAG, "onDestroy"); mScriptEngine.put("activity", null); mScriptEngine.setTag("activity", null); mScriptEngine.destroy(); @@ -151,10 +149,8 @@ public class ScriptExecuteActivity extends AppCompatActivity { @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - if (mIntentExtras == null) - return; - IntentExtras extras = IntentExtras.newExtras().putAll(mIntentExtras); - outState.putInt(IntentExtras.EXTRA_ID, extras.getId()); + if (mScriptExecution != null) + outState.putInt(EXTRA_EXECUTION_ID, mScriptExecution.getId()); emit("save_instance_state", outState); } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java index 525c45de..a8493e44 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.content.Context; import android.os.Build; import android.os.Looper; +import android.util.Log; import com.stardust.app.GlobalAppContext; import com.stardust.autojs.R; @@ -333,7 +334,7 @@ public class ScriptRuntime { } } - public void loadDex(String path){ + public void loadDex(String path) { path = files.path(path); try { ((AndroidClassLoader) ContextFactory.getGlobal().getApplicationClassLoader()).loadDex(new File(path)); @@ -375,6 +376,7 @@ public class ScriptRuntime { } public void onExit() { + Log.d(TAG, "on exit"); //清除interrupt状态 ThreadCompat.interrupted(); //悬浮窗需要第一时间关闭以免出现恶意脚本全屏悬浮窗屏蔽屏幕并且在exit中写死循环的问题 @@ -398,6 +400,7 @@ public class ScriptRuntime { } ignoresException(sensors::unregisterAll); ignoresException(timers::recycle); + ignoresException(ui::recycle); } private void ignoresException(Runnable r) { diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java index a2964dee..06cebbe6 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Sensors.java @@ -17,7 +17,6 @@ import java.lang.reflect.Field; import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; /** * Created by Stardust on 2018/2/5. @@ -92,7 +91,7 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler { mScriptBridges = runtime.bridges; mNoOpSensorEventEmitter = new SensorEventEmitter(runtime.bridges); mScriptRuntime = runtime; - runtime.loopers.addLooperQuiteHandler(this); + runtime.loopers.addLooperQuitHandler(this); } public SensorEventEmitter register(String sensorName) { @@ -167,5 +166,6 @@ public class Sensors extends EventEmitter implements Loopers.LooperQuitHandler { } mSensorEventEmitters.clear(); } + mScriptRuntime.loopers.removeLooperQuitHandler(this); } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java index 3ee193cd..e7b3980a 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UI.java @@ -113,6 +113,10 @@ public class UI extends ProxyObject { } } + public void recycle(){ + mDynamicLayoutInflater.setContext(null); + } + private class Drawables extends com.stardust.autojs.core.ui.inflater.util.Drawables { @Override