6.7.0 - Alpha19 - Fine tuning

This commit is contained in:
SuperMonster003
2026-01-31 18:52:24 +08:00
parent 142c465914
commit 9ffca28207
15 changed files with 123 additions and 99 deletions

View File

@@ -98,7 +98,7 @@ open class PointerLocationTool(final override val context: Context) : ShowableIt
runCatching byShizuku@{ runCatching byShizuku@{
when { when {
WrappedShizuku.isOperational() -> { WrappedShizuku.hasService() && WrappedShizuku.isOperational() -> {
WrappedShizuku.execCommand(context, cmd).result.trim().toIntOrNull() WrappedShizuku.execCommand(context, cmd).result.trim().toIntOrNull()
} }
else -> null else -> null

View File

@@ -12,7 +12,7 @@ object LooperThread {
fun getLooperOrNull(thread: Thread) = when { fun getLooperOrNull(thread: Thread) = when {
isEqual(thread, Looper.getMainLooper().thread) -> Looper.getMainLooper() isEqual(thread, Looper.getMainLooper().thread) -> Looper.getMainLooper()
thread is ILooperThread -> (thread as ILooperThread).looper thread is ILooperThread -> thread.looper
else -> null else -> null
} }

View File

@@ -12,18 +12,19 @@ import org.autojs.autojs.runtime.exception.ScriptInterruptedException
import org.mozilla.javascript.BaseFunction import org.mozilla.javascript.BaseFunction
import org.mozilla.javascript.Context import org.mozilla.javascript.Context
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.* import java.util.WeakHashMap
import java.util.concurrent.CountDownLatch
/** /**
* Created by Stardust on Dec 27, 2017. * Created by Stardust on Dec 27, 2017.
* Modified by SuperMonster003 as of Jan 31, 2026.
*/ */
open class TimerThread( open class TimerThread(
scriptRuntime: ScriptRuntime, scriptRuntime: ScriptRuntime,
private val target: Runnable, private val target: Runnable,
) : ThreadCompat(target), ILooperThread { ) : ThreadCompat(target), ILooperThread {
private var mRunning = false private val mRunningLatch = CountDownLatch(1)
private val mRunningLock = Object()
private var mWeakRuntime = WeakReference(scriptRuntime) private var mWeakRuntime = WeakReference(scriptRuntime)
@Volatile @Volatile
@@ -32,54 +33,43 @@ open class TimerThread(
@Volatile @Volatile
private var mLooper: Looper? = null private var mLooper: Looper? = null
override val looper: Looper? = mLooper override val looper: Looper?
get() = mLooper
var loopers: Loopers? = null
val timer: Timer
get() {
checkNotNull(mTimer) { "thread is not alive" }
return mTimer as Timer
}
override fun run() { override fun run() {
val scriptRuntime = mWeakRuntime.get() ?: return val scriptRuntime = mWeakRuntime.get() ?: return
scriptRuntime.loopers.prepare() scriptRuntime.loopers.prepare()
var timer: Timer
mTimer = scriptRuntime.timers.newTimer(scriptRuntime).also { timer = it } scriptRuntime.timers.newTimer(scriptRuntime).also {
sTimerMap[currentThread()] = WeakReference<Timer>(timer) mTimer = it
(scriptRuntime.engines.myEngine() as? RhinoJavaScriptEngine)?.enterContext() sTimerMap[currentThread()] = WeakReference<Timer>(it)
}
val engine = scriptRuntime.engines.myEngine() as? RhinoJavaScriptEngine
engine?.enterContext()
notifyRunning() notifyRunning()
Looper.myLooper().also { setLooper(it) }
?.let { Handler(it).post(target) } val currentLooper = Looper.myLooper()
try { setLooper(currentLooper)
Looper.loop() currentLooper?.let { Handler(it).post(target) }
onExit()
mTimer = null val exceptionHandler: (t: Throwable) -> Unit = { t ->
} catch (throwable: Throwable) { runCatching {
try { if (!ScriptInterruptedException.causedByInterrupt(t)) {
if (ScriptInterruptedException.causedByInterrupt(throwable)) { val console: Console = mWeakRuntime.get()?.console ?: AutoJs.instance.globalConsole
return console.error("${currentThread()}: $t")
} }
var console: Console? = null
val runtime = mWeakRuntime.get()
if (runtime != null) {
console = runtime.console
}
if (console == null) {
console = AutoJs.instance.globalConsole
}
console.error("${Thread.currentThread()}: $throwable")
} finally {
onExit()
mTimer = null
Context.exit()
sTimerMap.remove(currentThread())
} }
} }
runCatching { Context.exit() }
sTimerMap.remove(currentThread()) runCatching { Looper.loop() }.onFailure(exceptionHandler)
} runCatching { onExit() }.onFailure(exceptionHandler)
mTimer = null
runCatching { Context.exit() }.onFailure(exceptionHandler)
sTimerMap.remove(currentThread())
}
override fun interrupt() { override fun interrupt() {
LooperHelper.quit(LooperThread.getLooperOrNull(this)) LooperHelper.quit(LooperThread.getLooperOrNull(this))
@@ -96,46 +86,58 @@ open class TimerThread(
@Throws(InterruptedException::class) @Throws(InterruptedException::class)
fun waitFor() { fun waitFor() {
synchronized(mRunningLock) { mRunningLatch.await()
if (!mRunning) {
mRunningLock.wait()
}
}
} }
fun setTimeout(callback: BaseFunction): Double = setTimeout(callback, 1) fun setTimeout(callback: BaseFunction): Double =
setTimeout(callback, 1)
fun setTimeout(callback: BaseFunction, delay: Long, vararg args: Any): Double = timer.setTimeout(callback, delay, args.copyOf()) fun setTimeout(callback: BaseFunction, delay: Long, vararg args: Any): Double = withTimer {
setTimeout(callback, delay, args.copyOf())
}
fun clearTimeout(id: Double) = timer.clearTimeout(id) fun clearTimeout(id: Double): Boolean = withTimer {
clearTimeout(id)
}
fun setInterval(callback: BaseFunction) = setInterval(callback, 1L) fun setInterval(callback: BaseFunction): Double =
setInterval(callback, 1L)
fun setInterval(callback: BaseFunction, interval: Long, vararg args: Any) = timer.setInterval(callback, interval, args.copyOf()) fun setInterval(callback: BaseFunction, interval: Long, vararg args: Any): Double = withTimer {
setInterval(callback, interval, args.copyOf())
}
fun clearInterval(id: Double) = timer.clearInterval(id) fun clearInterval(id: Double): Boolean = withTimer {
clearInterval(id)
}
fun setImmediate(callback: BaseFunction, vararg args: Any) = timer.setImmediate(callback, args.copyOf()) fun setImmediate(callback: BaseFunction, vararg args: Any): Double = withTimer {
setImmediate(callback, args.copyOf())
}
fun clearImmediate(id: Double) = timer.clearImmediate(id) fun clearImmediate(id: Double): Boolean = withTimer {
clearImmediate(id)
}
private inline fun <R> withTimer(callback: Timer.() -> R): R {
val timer = mTimer
checkNotNull(timer) { "Thread is not alive" }
return callback(timer)
}
private fun setLooper(looper: Looper?) { private fun setLooper(looper: Looper?) {
mLooper = looper mLooper = looper
} }
private fun notifyRunning() { private fun notifyRunning() {
synchronized(mRunningLock) { mRunningLatch.countDown()
mRunning = true
mRunningLock.notifyAll()
}
} }
companion object { companion object {
private val sTimerMap = WeakHashMap<Thread, WeakReference<Timer>>() private val sTimerMap = WeakHashMap<Thread, WeakReference<Timer>>()
@JvmStatic @JvmStatic
fun getTimerForThread(thread: Thread) = sTimerMap[thread]?.get() fun getTimerForThread(thread: Thread) = sTimerMap[thread]?.get()
} }
} }

View File

@@ -1037,10 +1037,9 @@ public class Dim {
@Override @Override
public void onEngineCreate(ScriptEngine<? extends ScriptSource> engine) { public void onEngineCreate(ScriptEngine<? extends ScriptSource> engine) {
if (type != IPROXY_LISTEN) Kit.codeBug(); if (type != IPROXY_LISTEN) Kit.codeBug();
if (!(engine instanceof RhinoJavaScriptEngine) ||
!callback.shouldAttachDebugger((RhinoJavaScriptEngine) engine)) { if (!(engine instanceof RhinoJavaScriptEngine)) return;
return; if (!callback.shouldAttachDebugger((RhinoJavaScriptEngine) engine)) return;
}
Context cx = ((RhinoJavaScriptEngine) engine).getContext(); Context cx = ((RhinoJavaScriptEngine) engine).getContext();
ContextData contextData = new ContextData(); ContextData contextData = new ContextData();

View File

@@ -45,7 +45,7 @@ public class Dialogs {
MaterialDialog.Builder builder = dialogBuilder(callback) MaterialDialog.Builder builder = dialogBuilder(callback)
.alert() .alert()
.title(title) .title(title)
.positiveText(R.string.text_ok); .positiveText(R.string.dialog_button_dismiss);
if (!TextUtils.isEmpty(content)) { if (!TextUtils.isEmpty(content)) {
builder.content(content); builder.content(content);
} }
@@ -57,8 +57,8 @@ public class Dialogs {
MaterialDialog.Builder builder = dialogBuilder(callback) MaterialDialog.Builder builder = dialogBuilder(callback)
.confirm() .confirm()
.title(title) .title(title)
.positiveText(R.string.text_ok) .positiveText(R.string.dialog_button_confirm)
.negativeText(R.string.text_cancel); .negativeText(R.string.dialog_button_cancel);
if (!TextUtils.isEmpty(content)) { if (!TextUtils.isEmpty(content)) {
builder.content(content); builder.content(content);
} }
@@ -86,7 +86,7 @@ public class Dialogs {
return ((BlockedMaterialDialog.Builder) dialogBuilder(callback) return ((BlockedMaterialDialog.Builder) dialogBuilder(callback)
.itemsCallbackSingleChoice(selectedIndex) .itemsCallbackSingleChoice(selectedIndex)
.title(title) .title(title)
.positiveText(R.string.text_ok) .positiveText(R.string.dialog_button_confirm)
.items(items)) .items(items))
.showAndGet(); .showAndGet();
} }
@@ -96,7 +96,7 @@ public class Dialogs {
return ((BlockedMaterialDialog.Builder) dialogBuilder(callback) return ((BlockedMaterialDialog.Builder) dialogBuilder(callback)
.itemsCallbackMultiChoice(ArrayUtils.box(indices)) .itemsCallbackMultiChoice(ArrayUtils.box(indices))
.title(title) .title(title)
.positiveText(R.string.text_ok) .positiveText(R.string.dialog_button_confirm)
.items(items)) .items(items))
.showAndGet(); .showAndGet();
} }

View File

@@ -43,7 +43,7 @@ class UI(context: Context, private val scriptRuntime: ScriptRuntime) : ProxyObje
it.context = context it.context = context
} }
private val mProperties = ConcurrentHashMap<String, Any?>().also { private val mProperties = ConcurrentHashMap<String, Any>().also {
it["layoutInflater"] = layoutInflater it["layoutInflater"] = layoutInflater
} }

View File

@@ -13,7 +13,7 @@ object Util {
fun getClassName(o: Any?) = getClassNameInternal(o, "getClassName") fun getClassName(o: Any?) = getClassNameInternal(o, "getClassName")
private fun getClassInternal(o: Any?, methodName: String): Class<out Any> { private fun getClassInternal(o: Any?, methodName: String): Class<out Any> {
require(o != null) { "Argument \"o\" ${o.jsBrief()} for util.$methodName must be non-null" } requireNotNull(o) { "Argument \"o\" ${o.jsBrief()} for util.$methodName must be non-null" }
return o as? Class<*> ?: o.javaClass return o as? Class<*> ?: o.javaClass
} }

View File

@@ -139,7 +139,7 @@ object WrappedShizuku {
} }
@ScriptInterface @ScriptInterface
fun isOperational() = hasService() && isRunning() && hasPermission() fun isOperational() = isRunning() && hasPermission()
@ScriptInterface @ScriptInterface
fun isRunning() = mHasBinder fun isRunning() = mHasBinder
@@ -147,6 +147,15 @@ object WrappedShizuku {
@ScriptInterface @ScriptInterface
fun hasService() = service != null fun hasService() = service != null
@JvmStatic
fun getServiceOrNull(): IUserService? {
service?.let { return it }
bindUserServiceIfNeeded()
initializeShizukuServiceAndWait(5000L)
service?.let { return it }
return null
}
@ScriptInterface @ScriptInterface
fun requestPermission() = Shizuku.requestPermission(mRequestCode) fun requestPermission() = Shizuku.requestPermission(mRequestCode)

View File

@@ -266,7 +266,7 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : A
} }
if (this is AsEmitter) { if (this is AsEmitter) {
require(scriptRuntime != null) { "Augmentable instance of AsEmitter must have a non-null scriptRuntime property" } requireNotNull(scriptRuntime) { "Augmentable instance of AsEmitter must have a non-null scriptRuntime property" }
objProtoList += Events.__asEmitter__(scriptRuntime, emptyArray()) objProtoList += Events.__asEmitter__(scriptRuntime, emptyArray())
} }

View File

@@ -1170,7 +1170,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
var bitmap: Bitmap? = null var bitmap: Bitmap? = null
try { try {
image = read(scriptRuntime, argList) image = read(scriptRuntime, argList)
require(image != null) { "Image path ${argList[0]} is invalid for images.readPixels" } requireNotNull(image) { "Image path ${argList[0]} is invalid for images.readPixels" }
bitmap = image.bitmap bitmap = image.bitmap
val w = bitmap.width val w = bitmap.width
val h = bitmap.height val h = bitmap.height

View File

@@ -81,7 +81,7 @@ internal fun extendBuildInObjectInternal(scriptRuntime: ScriptRuntime, augmentab
} }
protoList.forEach { pair -> protoList.forEach { pair ->
val (funcName, attributes) = pair val (funcName, attributes) = pair
require(extensibleProtoClass != null) { "A proto class must be specified for build-in object prototype extension" } requireNotNull(extensibleProtoClass) { "A proto class must be specified for build-in object prototype extension" }
val prototypeObject = buildInObject.prop("prototype") as ScriptableObject val prototypeObject = buildInObject.prop("prototype") as ScriptableObject

View File

@@ -3,9 +3,14 @@ package org.autojs.autojs.runtime.api.augment.shell
import android.util.Log import android.util.Log
import android.view.KeyEvent import android.view.KeyEvent
import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.rhino.ArgumentGuards
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component1
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component2
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component3
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component4
import org.autojs.autojs.rhino.ArgumentGuards.Companion.component5
import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish import org.autojs.autojs.rhino.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief import org.autojs.autojs.rhino.extension.AnyExtensions.jsBrief
import org.autojs.autojs.rhino.ArgumentGuards
import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.AbstractShell import org.autojs.autojs.runtime.api.AbstractShell
import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.api.augment.Augmentable
@@ -132,16 +137,17 @@ class Shell(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim
process.inputStream.bufferedReader().useLines { lines -> process.inputStream.bufferedReader().useLines { lines ->
val resumedActivityLine = lines.find { val resumedActivityLine = lines.find {
it.contains("Resumed:") || it.contains("ResumedActivity") it.contains("Resumed:") || it.contains("ResumedActivity")
} } ?: return@useLines
resumedActivityLine?.let { line ->
Log.d(TAG, "Found Resumed Activity: $line") Log.d(TAG, "Found Resumed Activity: $resumedActivityLine")
line.split("\\s+".toRegex()).firstOrNull { part ->
part.contains("/") val activityPart = resumedActivityLine.split("\\s+".toRegex()).firstOrNull { part ->
}?.let { part -> part.contains("/")
Log.d(TAG, "current activity part: $part") } ?: return@useLines
return part.replace("\\W+$".toRegex(), "")
} Log.d(TAG, "current activity part: $activityPart")
}
return activityPart.replace("\\W+$".toRegex(), "")
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error reading current component", e) Log.e(TAG, "Error reading current component", e)

View File

@@ -28,6 +28,7 @@ class Shizuku(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt
"state" to Supplier { "state" to Supplier {
newNativeObject().also { o -> newNativeObject().also { o ->
o.defineProp("isInstalled", WrappedShizuku.isInstalled(globalContext)) o.defineProp("isInstalled", WrappedShizuku.isInstalled(globalContext))
o.defineProp("hasService", WrappedShizuku.hasService())
o.defineProp("isRunning", WrappedShizuku.isRunning()) o.defineProp("isRunning", WrappedShizuku.isRunning())
o.defineProp("hasPermission", WrappedShizuku.hasPermission()) o.defineProp("hasPermission", WrappedShizuku.hasPermission())
o.defineProp("isOperational", WrappedShizuku.isOperational()) o.defineProp("isOperational", WrappedShizuku.isOperational())

View File

@@ -24,6 +24,7 @@ import org.autojs.autojs.core.pref.Language;
import org.autojs.autojs.core.pref.Pref; import org.autojs.autojs.core.pref.Pref;
import org.autojs.autojs.core.record.GlobalActionRecorder; import org.autojs.autojs.core.record.GlobalActionRecorder;
import org.autojs.autojs.core.record.Recorder; import org.autojs.autojs.core.record.Recorder;
import org.autojs.autojs.core.shizuku.IUserService;
import org.autojs.autojs.model.explorer.ExplorerDirPage; import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.ExplorerPage; import org.autojs.autojs.model.explorer.ExplorerPage;
import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.explorer.Explorers;
@@ -414,9 +415,12 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private String getCurrentPackage() { private String getCurrentPackage() {
if (WrappedShizuku.INSTANCE.isOperational()) { if (WrappedShizuku.INSTANCE.isOperational()) {
try { try {
mCurrentPackage = Objects.requireNonNull(WrappedShizuku.service).currentPackage(); IUserService service = WrappedShizuku.getServiceOrNull();
if (!TextUtils.isEmpty(mCurrentPackage)) { if (service != null) {
return mCurrentPackage; mCurrentPackage = service.currentPackage();
if (!TextUtils.isEmpty(mCurrentPackage)) {
return mCurrentPackage;
}
} }
} catch (RemoteException ignored) { } catch (RemoteException ignored) {
/* Ignored. */ /* Ignored. */
@@ -439,9 +443,12 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private String getCurrentActivity() { private String getCurrentActivity() {
if (WrappedShizuku.INSTANCE.isOperational()) { if (WrappedShizuku.INSTANCE.isOperational()) {
try { try {
mCurrentActivity = Objects.requireNonNull(WrappedShizuku.service).currentActivity(); IUserService service = WrappedShizuku.getServiceOrNull();
if (!TextUtils.isEmpty(mCurrentActivity)) { if (service != null) {
return mCurrentActivity; mCurrentActivity = service.currentActivity();
if (!TextUtils.isEmpty(mCurrentActivity)) {
return mCurrentActivity;
}
} }
} catch (RemoteException ignored) { } catch (RemoteException ignored) {
/* Ignored. */ /* Ignored. */

View File

@@ -1,5 +1,5 @@
#Sat Jan 31 15:04:03 CST 2026 #Sat Jan 31 18:47:47 CST 2026
BUILD_TIME=1769843043403 BUILD_TIME=1769856467115
COMPILE_SDK_VERSION=36 COMPILE_SDK_VERSION=36
IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125 IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=36 TARGET_SDK_VERSION=36
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3678 VERSION_BUILD=3679
VERSION_NAME=6.7.0 Alpha19 VERSION_NAME=6.7.0 Alpha19
VSCODE_EXT_REQUIRED_VERSION=1.0.13 VSCODE_EXT_REQUIRED_VERSION=1.0.13