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@{
when {
WrappedShizuku.isOperational() -> {
WrappedShizuku.hasService() && WrappedShizuku.isOperational() -> {
WrappedShizuku.execCommand(context, cmd).result.trim().toIntOrNull()
}
else -> null

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ object Util {
fun getClassName(o: Any?) = getClassNameInternal(o, "getClassName")
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
}

View File

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

View File

@@ -266,7 +266,7 @@ abstract class Augmentable(private val scriptRuntime: ScriptRuntime? = null) : A
}
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())
}

View File

@@ -1170,7 +1170,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
var bitmap: Bitmap? = null
try {
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
val w = bitmap.width
val h = bitmap.height

View File

@@ -81,7 +81,7 @@ internal fun extendBuildInObjectInternal(scriptRuntime: ScriptRuntime, augmentab
}
protoList.forEach { 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

View File

@@ -3,9 +3,14 @@ package org.autojs.autojs.runtime.api.augment.shell
import android.util.Log
import android.view.KeyEvent
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.jsBrief
import org.autojs.autojs.rhino.ArgumentGuards
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.AbstractShell
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 ->
val resumedActivityLine = lines.find {
it.contains("Resumed:") || it.contains("ResumedActivity")
}
resumedActivityLine?.let { line ->
Log.d(TAG, "Found Resumed Activity: $line")
line.split("\\s+".toRegex()).firstOrNull { part ->
part.contains("/")
}?.let { part ->
Log.d(TAG, "current activity part: $part")
return part.replace("\\W+$".toRegex(), "")
}
}
} ?: return@useLines
Log.d(TAG, "Found Resumed Activity: $resumedActivityLine")
val activityPart = resumedActivityLine.split("\\s+".toRegex()).firstOrNull { part ->
part.contains("/")
} ?: return@useLines
Log.d(TAG, "current activity part: $activityPart")
return activityPart.replace("\\W+$".toRegex(), "")
}
} catch (e: Exception) {
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 {
newNativeObject().also { o ->
o.defineProp("isInstalled", WrappedShizuku.isInstalled(globalContext))
o.defineProp("hasService", WrappedShizuku.hasService())
o.defineProp("isRunning", WrappedShizuku.isRunning())
o.defineProp("hasPermission", WrappedShizuku.hasPermission())
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.record.GlobalActionRecorder;
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.ExplorerPage;
import org.autojs.autojs.model.explorer.Explorers;
@@ -414,9 +415,12 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private String getCurrentPackage() {
if (WrappedShizuku.INSTANCE.isOperational()) {
try {
mCurrentPackage = Objects.requireNonNull(WrappedShizuku.service).currentPackage();
if (!TextUtils.isEmpty(mCurrentPackage)) {
return mCurrentPackage;
IUserService service = WrappedShizuku.getServiceOrNull();
if (service != null) {
mCurrentPackage = service.currentPackage();
if (!TextUtils.isEmpty(mCurrentPackage)) {
return mCurrentPackage;
}
}
} catch (RemoteException ignored) {
/* Ignored. */
@@ -439,9 +443,12 @@ public class CircularMenu implements LayoutInspector.CaptureAvailableListener {
private String getCurrentActivity() {
if (WrappedShizuku.INSTANCE.isOperational()) {
try {
mCurrentActivity = Objects.requireNonNull(WrappedShizuku.service).currentActivity();
if (!TextUtils.isEmpty(mCurrentActivity)) {
return mCurrentActivity;
IUserService service = WrappedShizuku.getServiceOrNull();
if (service != null) {
mCurrentActivity = service.currentActivity();
if (!TextUtils.isEmpty(mCurrentActivity)) {
return mCurrentActivity;
}
}
} catch (RemoteException ignored) {
/* Ignored. */