From 2312e610bfbc327b472af0fb6416e8b5c1c3e5df Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Mon, 17 Dec 2018 23:06:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20auto.setFlags("useShell")?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E4=BD=BF=E7=94=A8shell=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=BD=93=E5=89=8D=E6=B4=BB=E5=8A=A8=E5=92=8C=E5=BD=93?= =?UTF-8?q?=E5=89=8D=E5=8C=85=E5=90=8D=EF=BC=8C=E6=9B=B4=E5=8A=A0=E5=87=86?= =?UTF-8?q?=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/caches/build_file_checksums.ser | Bin 733 -> 733 bytes app/build.gradle | 9 + .../src/main/assets/modules/__automator__.js | 8 +- .../main/java/com/stardust/autojs/AutoJs.java | 16 +- .../accessibility/AccessibilityBridge.java | 8 +- .../core/activity/ActivityInfoProvider.kt | 181 ++++++++++++++++++ .../autojs/runtime/ScriptRuntime.java | 4 +- .../AccessibilityInfoProvider.kt | 87 --------- 8 files changed, 212 insertions(+), 101 deletions(-) create mode 100644 autojs/src/main/java/com/stardust/autojs/core/activity/ActivityInfoProvider.kt delete mode 100644 automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.kt diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 00ea882a72393f4ec991d232f5674bec6762f956..829c685001c47f1a45b273e8d24a3eb7f1548181 100644 GIT binary patch delta 36 ucmV+<0NelF1>FUZm;}6`DF>09cMxhnBZX}`>KHhHl4F00lEPx6%XkE delta 36 ucmV+<0NelF1>FUZm;|+spjMHbcM$oi-*}0O2= Build.VERSION_CODES.LOLLIPOP) { @@ -89,7 +92,7 @@ public abstract class AccessibilityBridge { mWindowFilter = windowFilter; } - public abstract AccessibilityInfoProvider getInfoProvider(); + public abstract ActivityInfoProvider getInfoProvider(); public void setMode(int mode) { mMode = mode; @@ -108,6 +111,7 @@ public abstract class AccessibilityBridge { } } getInfoProvider().setUseUsageStats((mFlags & FLAG_USE_USAGE_STATS) != 0); + getInfoProvider().setUseShell((mFlags & FLAG_USE_SHELL) != 0); } @NonNull diff --git a/autojs/src/main/java/com/stardust/autojs/core/activity/ActivityInfoProvider.kt b/autojs/src/main/java/com/stardust/autojs/core/activity/ActivityInfoProvider.kt new file mode 100644 index 00000000..02393978 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/activity/ActivityInfoProvider.kt @@ -0,0 +1,181 @@ +package com.stardust.autojs.core.activity + +import android.accessibilityservice.AccessibilityService +import android.app.AppOpsManager +import android.app.usage.UsageStatsManager +import android.content.ComponentName +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.util.Log +import android.view.accessibility.AccessibilityEvent +import androidx.annotation.RequiresApi +import com.stardust.app.isOpPermissionGranted +import com.stardust.autojs.core.util.Shell +import com.stardust.view.accessibility.AccessibilityDelegate +import java.util.regex.Pattern + +/** + * Created by Stardust on 2017/3/9. + */ + +class ActivityInfoProvider(private val context: Context) : AccessibilityDelegate { + + private val mPackageManager: PackageManager = context.packageManager + + @Volatile + private var mLatestPackage: String = "" + @Volatile + private var mLatestActivity: String = "" + private var mLatestComponentFromShell: ComponentName? = null + + private var mShell: Shell? = null + private var mUseShell = false + + val latestPackage: String + get() { + val compFromShell = mLatestComponentFromShell + if (useShell && compFromShell != null) { + return compFromShell.packageName + } + if (useUsageStats && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + mLatestPackage = getLatestPackageByUsageStats() + } + return mLatestPackage + } + + val latestActivity: String + get() { + val compFromShell = mLatestComponentFromShell + if (useShell && compFromShell != null) { + return compFromShell.className + } + return mLatestActivity + } + + var useUsageStats: Boolean = false + + var useShell: Boolean + get() = mUseShell + set(value) { + if (value) { + mShell.let { + if (it == null) { + mShell = createShell(200) + } + } + } else { + mShell?.exit() + mShell = null + } + mUseShell = value + } + + override val eventTypes: Set? + get() = AccessibilityDelegate.ALL_EVENT_TYPES + + override fun onAccessibilityEvent(service: AccessibilityService, event: AccessibilityEvent): Boolean { + if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { + setLatestComponent(event.packageName, event.className) + } + return false + } + + fun getLatestPackageByUsageStatsIfGranted(): String { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && context.isOpPermissionGranted(AppOpsManager.OPSTR_GET_USAGE_STATS)) { + return getLatestPackageByUsageStats() + } + return mLatestPackage + } + + private fun setLatestComponentFromShellOutput(output: String) { + val matcher = WINDOW_PATTERN.matcher(output) + if (!matcher.find() || matcher.groupCount() < 1) { + Log.w(LOG_TAG, "invalid format: $output") + return + } + val latestPackage = matcher.group(1) + if (latestPackage.contains(":")) { + return + } + val latestActivity = if (matcher.groupCount() >= 2) { + matcher.group(2).orEmpty() + } else { + "" + } + Log.d(LOG_TAG, "setLatestComponent: output = $output, comp = $latestPackage/$latestActivity") + mLatestComponentFromShell = ComponentName(latestPackage, latestActivity) + } + + private fun createShell(dumpInterval: Int): Shell { + val shell = Shell(true) + shell.setCallback(object : Shell.Callback { + override fun onOutput(str: String) { + + } + + override fun onNewLine(line: String) { + setLatestComponentFromShellOutput(line) + } + + override fun onInitialized() { + } + + override fun onInterrupted(e: InterruptedException) { + + } + }) + shell.exec(DUMP_WINDOW_COMMAND.format(dumpInterval)) + return shell + } + + @RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1) + fun getLatestPackageByUsageStats(): String { + val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager + val current = System.currentTimeMillis() + val usageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, current - 60 * 60 * 1000, current) + return if (usageStats.isEmpty()) { + mLatestPackage + } else { + usageStats.sortBy { + it.lastTimeStamp + } + usageStats.last().packageName + } + + } + + private fun setLatestComponent(latestPackage: CharSequence?, latestClass: CharSequence?) { + if (latestPackage == null || latestClass == null) + return + val latestPackageStr = latestPackage.toString() + val latestClassStr = latestClass.toString() + if (latestClassStr.startsWith("android.view.") || latestClassStr.startsWith("android.widget.")) + return + try { + val componentName = ComponentName(latestPackageStr, latestClassStr) + mLatestActivity = mPackageManager.getActivityInfo(componentName, PackageManager.MATCH_DEFAULT_ONLY).name + } catch (ignored: PackageManager.NameNotFoundException) { + return + } + mLatestPackage = latestPackage.toString() + } + + companion object { + private val WINDOW_PATTERN = Pattern.compile("Window\\{\\S+\\s\\S+\\s([^\\/]+)\\/?([^}]+)?\\}") + private val DUMP_WINDOW_COMMAND = """ + oldActivity="" + currentActivity=`dumpsys window windows | grep -E 'mCurrentFocus'` + while true + do + if [[ ${'$'}oldActivity != ${'$'}currentActivity && ${'$'}currentActivity != *"=null"* ]]; then + echo ${'$'}currentActivity + oldActivity=${'$'}currentActivity + fi + currentActivity=`dumpsys window windows | grep -E 'mCurrentFocus'` + done + """.trimIndent() + + private const val LOG_TAG = "ActivityInfoProvider" + } +} 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 93a7b3c9..2fe5f3e0 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/ScriptRuntime.java @@ -47,7 +47,7 @@ import com.stardust.util.ScreenMetrics; import com.stardust.util.SdkVersionUtil; import com.stardust.util.Supplier; import com.stardust.util.UiHandler; -import com.stardust.view.accessibility.AccessibilityInfoProvider; +import com.stardust.autojs.core.activity.ActivityInfoProvider; import org.mozilla.javascript.ContextFactory; import org.mozilla.javascript.RhinoException; @@ -140,7 +140,7 @@ public class ScriptRuntime { public final SimpleActionAutomator automator; @ScriptVariable - public final AccessibilityInfoProvider info; + public final ActivityInfoProvider info; @ScriptVariable public final UI ui; diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.kt b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.kt deleted file mode 100644 index 8d6892a4..00000000 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityInfoProvider.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.stardust.view.accessibility - -import android.accessibilityservice.AccessibilityService -import android.app.AppOpsManager -import android.app.usage.UsageStatsManager -import android.content.ComponentName -import android.content.Context -import android.content.pm.PackageManager -import android.os.Build -import android.view.accessibility.AccessibilityEvent -import androidx.annotation.RequiresApi -import com.stardust.app.isOpPermissionGranted - -/** - * Created by Stardust on 2017/3/9. - */ - -class AccessibilityInfoProvider(private val context: Context) : AccessibilityDelegate { - - private val mPackageManager: PackageManager = context.packageManager - - @Volatile - private var mLatestPackage: String = "" - - val latestPackage: String - get() { - if (useUsageStats && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - mLatestPackage = getLatestPackageByUsageStats() - } - return mLatestPackage - } - - @Volatile - var latestActivity = "" - private set - - var useUsageStats: Boolean = false - - override val eventTypes: Set? - get() = AccessibilityDelegate.ALL_EVENT_TYPES - - override fun onAccessibilityEvent(service: AccessibilityService, event: AccessibilityEvent): Boolean { - if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { - setLatestComponent(event.packageName, event.className) - } - return false - } - - fun getLatestPackageByUsageStatsIfGranted(): String { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && context.isOpPermissionGranted(AppOpsManager.OPSTR_GET_USAGE_STATS)) { - return getLatestPackageByUsageStats() - } - return mLatestPackage - } - - @RequiresApi(Build.VERSION_CODES.LOLLIPOP_MR1) - fun getLatestPackageByUsageStats(): String { - val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager - val current = System.currentTimeMillis() - val usageStats = usageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_BEST, current - 60 * 60 * 1000, current) - return if (usageStats.isEmpty()) { - mLatestPackage - } else { - usageStats.sortBy { - it.lastTimeStamp - } - usageStats.last().packageName - } - - } - - private fun setLatestComponent(latestPackage: CharSequence?, latestClass: CharSequence?) { - if (latestPackage == null || latestClass == null) - return - val latestPackageStr = latestPackage.toString() - val latestClassStr = latestClass.toString() - if (latestClassStr.startsWith("android.view.") || latestClassStr.startsWith("android.widget.")) - return - try { - val componentName = ComponentName(latestPackageStr, latestClassStr) - latestActivity = mPackageManager.getActivityInfo(componentName, PackageManager.MATCH_DEFAULT_ONLY).name - } catch (ignored: PackageManager.NameNotFoundException) { - return - } - mLatestPackage = latestPackage.toString() - } -}