From 6a3392cfe6bdaf576811452f8c83788ca228ce39 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Tue, 1 Aug 2017 21:42:32 +0800 Subject: [PATCH] add: root_automator --- .idea/dictionaries/Stardust.xml | 1 + .../documentation/事件与按键、触摸监听.md | 26 +++- app/src/main/assets/js/functions.json | 20 +-- .../stardust/scriptdroid/autojs/AutoJs.java | 10 ++ .../floatingwindow/menu/HoverMenuService.java | 4 +- .../menu/content/RecordNavigatorContent.java | 3 - .../scriptdroid/ui/common/ProgressDialog.java | 6 +- .../scriptdroid/ui/main/SideMenuFragment.java | 10 +- app/src/main/res/values/strings.xml | 1 + autojs/src/main/assets/binary/root_automator | Bin 0 -> 13612 bytes .../src/main/assets/javascript_engine_init.js | 2 +- .../preprocess/RootAutomatorEngine.java | 8 ++ .../autojs/runtime/AccessibilityBridge.java | 5 + .../stardust/autojs/runtime/api/Events.java | 52 +++++++- .../autojs/runtime/api/InputEventSender.java | 86 ------------- .../autojs/runtime/api/RootAutomator.java | 112 ++++++++++++++++ .../record/inputevent/InputDevice.java | 8 ++ .../InputEventToRootAutomatorConverter.java | 120 ++++++++++++++++++ .../record/inputevent/TouchRecorder.java | 2 +- .../res/xml/accessibility_service_config.xml | 2 +- .../accessibility/NotificationListener.java | 97 ++++++++++++++ .../java/com/stardust/util/ArrayUtils.java | 11 ++ 22 files changed, 474 insertions(+), 112 deletions(-) create mode 100644 autojs/src/main/assets/binary/root_automator create mode 100644 autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java delete mode 100644 autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java create mode 100644 autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java create mode 100644 autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java create mode 100644 autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java create mode 100644 automator/src/main/java/com/stardust/view/accessibility/NotificationListener.java diff --git a/.idea/dictionaries/Stardust.xml b/.idea/dictionaries/Stardust.xml index 60983c2a..803965af 100644 --- a/.idea/dictionaries/Stardust.xml +++ b/.idea/dictionaries/Stardust.xml @@ -3,6 +3,7 @@ dismissable interruptible + loopers prefill scriptable tasker diff --git a/app/src/main/assets/help/documentation/事件与按键、触摸监听.md b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md index a12f7a4b..57c868b1 100644 --- a/app/src/main/assets/help/documentation/事件与按键、触摸监听.md +++ b/app/src/main/assets/help/documentation/事件与按键、触摸监听.md @@ -89,7 +89,7 @@ events.onKeyDown("menu", function(event){ ### events.onTouch(listener) * listener \ 参数为Point的函数 -注册一个触摸监听函数。 +注册一个触摸监听函数。相当于`on("touch", listener)`。 例如: ``` @@ -147,6 +147,28 @@ events.loop(); ``` +### obverseNotification() + + + + +### toast事件 + + + +### 事件: 'notification' +* notification \ 通知 + +``` +events.observeNotification(); +events.on("notification", function(notification){ + log(notification. +}); + +``` + + + # EventEmitter ### EventEmitter.defaultMaxListeners @@ -155,7 +177,7 @@ events.loop(); 设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。 -注意,与NodeJs不同,**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。 +注意,与Node.js不同,**这是一个硬性限制**。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。 ``` emitter.setMaxListeners(emitter.getMaxListeners() + 1); emitter.once('event', () => { diff --git a/app/src/main/assets/js/functions.json b/app/src/main/assets/js/functions.json index 3a6c03dc..aeea2c54 100644 --- a/app/src/main/assets/js/functions.json +++ b/app/src/main/assets/js/functions.json @@ -1,5 +1,5 @@ { - "global" : { + "global": { "modules": [ "app", "automator", @@ -39,7 +39,7 @@ "openConsole", "clearConsole" ], - "dialogs":[ + "dialogs": [ "rawInput", "input", "alert", @@ -142,12 +142,12 @@ "Text" ], "timers": [ - "loop", - "setTimeout", - "clearTimeout", - "setInterval", - "clearInterval", - "setImmediate", + "loop", + "setTimeout", + "clearTimeout", + "setInterval", + "clearInterval", + "setImmediate", "clearImmediate" ], "web": [ @@ -211,7 +211,7 @@ "error", "assert" ], - "dialogs":[ + "dialogs": [ "select", "singleChoice", "multiChoice", @@ -248,6 +248,8 @@ "onKeyUp", "onceKeyDown", "onceKeyUp", + "onToast", + "onNotification", "removeAllKeyDownListeners", "removeAllKeyUpListeners", "onTouch", diff --git a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java index 14cbb43d..d32bf329 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/AutoJs.java @@ -1,6 +1,7 @@ package com.stardust.scriptdroid.autojs; import android.app.Activity; +import android.app.Notification; import android.content.Context; import android.os.Build; import android.os.Bundle; @@ -36,6 +37,7 @@ import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.scriptdroid.ui.console.JraskaConsole; import com.stardust.view.accessibility.AccessibilityServiceUtils; import com.stardust.view.accessibility.LayoutInspector; +import com.stardust.view.accessibility.NotificationListener; /** @@ -55,6 +57,7 @@ public class AutoJs { } private final AccessibilityActionRecorder mAccessibilityActionRecorder = new AccessibilityActionRecorder(); + private final NotificationListener.Observer mNotificationObserver; private final LayoutInspector mLayoutInspector = new LayoutInspector(); private final Context mContext; private final UiHandler mUiHandler; @@ -68,6 +71,7 @@ public class AutoJs { mContext = context; mUiHandler = new UiHandler(context); mAppUtils = new AppUtils(context); + mNotificationObserver = new NotificationListener.Observer(context); mAccessibilityInfoProvider = new AccessibilityInfoProvider(context.getPackageManager()); mScriptEngineService = buildScriptEngineService(); addAccessibilityServiceDelegates(); @@ -130,6 +134,7 @@ public class AutoJs { private void addAccessibilityServiceDelegates() { AccessibilityService.addDelegate(100, mAccessibilityInfoProvider); + AccessibilityService.addDelegate(200, mNotificationObserver); AccessibilityService.addDelegate(300, mAccessibilityActionRecorder); } @@ -198,6 +203,11 @@ public class AutoJs { return mAccessibilityInfoProvider; } + @Override + public NotificationListener.Observer getNotificationObserver() { + return mNotificationObserver; + } + } private class ScreenCaptureRequesterImpl extends ScreenCaptureRequester.AbstractScreenCaptureRequester { diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java index 962a28f3..f33a831e 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/HoverMenuService.java @@ -20,7 +20,6 @@ import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.view.accessibility.NodeInfo; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutBoundsView; import com.stardust.scriptdroid.external.floatingwindow.menu.view.FloatingLayoutHierarchyView; -import com.stardust.scriptdroid.tool.AccessibilityServiceTool; import com.stardust.theme.ThemeColorManagerCompat; import com.stardust.util.IntentUtil; import com.stardust.util.MessageEvent; @@ -189,7 +188,6 @@ public class HoverMenuService extends Service { tryInitViews(); if (mWindowHoverMenu != null) mWindowHoverMenu.show(); - AccessibilityServiceTool.enableAccessibilityServiceByRootIfNeeded(); return START_STICKY; } @@ -200,6 +198,8 @@ public class HoverMenuService extends Service { if (eventBus.isRegistered(this)) eventBus.unregister(this); setIsRunning(false); + if (mWindowViewController == null) + return; mWindowViewController.removeView(mFloatingLayoutBoundsView); mWindowViewController.removeView(mFloatingLayoutHierarchyView); } diff --git a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java index c414ce56..3a67226d 100644 --- a/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java +++ b/app/src/main/java/com/stardust/scriptdroid/external/floatingwindow/menu/content/RecordNavigatorContent.java @@ -85,9 +85,6 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat ButterKnife.bind(this, mView); HoverMenuService.getEventBus().register(this); AccessibilityService.getStickOnKeyObserver().addListener(mVolumeKeyListener); - if (Pref.isRecordVolumeControlEnable()) { - AutoJs.getInstance().ensureAccessibilityServiceEnabled(); - } if (Pref.hasRecordTrigger()) { mKeyObserver = new KeyObserver(mContext); mKeyObserver.startListening(); diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java b/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java index f7fe0413..4560fa33 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/common/ProgressDialog.java @@ -14,10 +14,14 @@ public class ProgressDialog { private MaterialDialog mDialog; public ProgressDialog(Context context) { + this(context, R.string.text_on_progress); + } + + public ProgressDialog(Context context, int resId) { mDialog = new MaterialDialog.Builder(context) .progress(true, 0) .cancelable(false) - .content(R.string.text_on_progress) + .content(resId) .show(); } diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java index 99e5b3e3..5cf13a4c 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/main/SideMenuFragment.java @@ -133,7 +133,12 @@ public class SideMenuFragment extends android.support.v4.app.Fragment { AccessibilityServiceTool.goToAccessibilitySetting(); return; } - final ProgressDialog progress = new ProgressDialog(getContext()); + enableAccessibilityServiceByRoot(); + + } + + private void enableAccessibilityServiceByRoot() { + final ProgressDialog progress = new ProgressDialog(getContext(), R.string.text_enable_accessibility_service_by_root_ing); UnderuseExecutors.execute(new Runnable() { @Override public void run() { @@ -156,6 +161,9 @@ public class SideMenuFragment extends android.support.v4.app.Fragment { void setFloatingWindowEnable(CompoundButton button, boolean enable) { if (enable && !HoverMenuManger.isHoverMenuShowing()) { HoverMenuManger.showHoverMenu(); + if (Pref.enableAccessibilityServiceByRoot()) { + enableAccessibilityServiceByRoot(); + } } else if (!enable && HoverMenuManger.isHoverMenuShowing()) { HoverMenuManger.hideHoverMenu(); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1925ef59..72cf7c56 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -212,6 +212,7 @@ 使用root权限开启失败 处理中 删除失败 + 正在使用root权限启用无障碍服务 diff --git a/autojs/src/main/assets/binary/root_automator b/autojs/src/main/assets/binary/root_automator new file mode 100644 index 0000000000000000000000000000000000000000..341611a486b343bb87ef451eb1880837d0aefeaf GIT binary patch literal 13612 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 F{{_Nhuvh>9 literal 0 HcmV?d00001 diff --git a/autojs/src/main/assets/javascript_engine_init.js b/autojs/src/main/assets/javascript_engine_init.js index fe447a35..2f1c8d5d 100644 --- a/autojs/src/main/assets/javascript_engine_init.js +++ b/autojs/src/main/assets/javascript_engine_init.js @@ -47,4 +47,4 @@ require("__general__")(__runtime__, this); __importClass__(android.view.KeyEvent); __importClass__(com.stardust.autojs.runtime.api.Shell); -__importClass__(com.stardust.autojs.runtime.api.InputEventSender); +__importClass__(com.stardust.autojs.runtime.api.RootAutomator); diff --git a/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java b/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java new file mode 100644 index 00000000..5d4ee3f2 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/engine/preprocess/RootAutomatorEngine.java @@ -0,0 +1,8 @@ +package com.stardust.autojs.engine.preprocess; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class RootAutomatorEngine { +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java b/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java index 764efa6e..493602a8 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/AccessibilityBridge.java @@ -1,11 +1,13 @@ package com.stardust.autojs.runtime; import android.content.Context; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.accessibility.AccessibilityNodeInfo; import com.stardust.view.accessibility.AccessibilityInfoProvider; import com.stardust.view.accessibility.AccessibilityService; +import com.stardust.view.accessibility.NotificationListener; /** * Created by Stardust on 2017/4/2. @@ -37,6 +39,7 @@ public abstract class AccessibilityBridge { } + @NonNull public abstract AccessibilityInfoProvider getInfoProvider(); @@ -44,4 +47,6 @@ public abstract class AccessibilityBridge { mMode = mode; } + @NonNull + public abstract NotificationListener.Observer getNotificationObserver(); } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java index 97356ab6..b88cc342 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Events.java @@ -1,25 +1,24 @@ package com.stardust.autojs.runtime.api; +import android.app.Notification; import android.content.Context; import android.graphics.Point; import android.os.Handler; -import android.os.Looper; -import android.util.SparseArray; import android.view.KeyEvent; +import android.view.accessibility.AccessibilityEvent; import com.stardust.autojs.runtime.AccessibilityBridge; import com.stardust.autojs.runtime.ScriptException; import com.stardust.autojs.runtime.record.inputevent.TouchObserver; import com.stardust.view.accessibility.AccessibilityService; +import com.stardust.view.accessibility.NotificationListener; import com.stardust.view.accessibility.OnKeyListener; -import java.util.concurrent.ConcurrentHashMap; - /** * Created by Stardust on 2017/7/18. */ -public class Events extends EventEmitter implements OnKeyListener, TouchObserver.OnTouchEventListener { +public class Events extends EventEmitter implements OnKeyListener, TouchObserver.OnTouchEventListener, NotificationListener { private static final String PREFIX_KEY_DOWN = "__key_down__#"; private static final String PREFIX_KEY_UP = "__key_up__#"; @@ -32,6 +31,7 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver private boolean mListeningKey = false; private Loopers mLoopers; private Handler mHandler; + private boolean mListeningNotification = false; public Events(Context context, AccessibilityBridge accessibilityBridge, ScriptBridges bridges, Loopers loopers) { super(bridges); @@ -122,6 +122,25 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } + public void observeNotification() { + if (mListeningNotification) + return; + mListeningNotification = true; + mAccessibilityBridge.getNotificationObserver() + .addListener(this); + } + + public Events onNotification(Object listener) { + on("notification", listener); + return this; + } + + public Events onToast(Object listener) { + on("toast", listener); + return this; + } + + public void recycle() { if (mListeningKey) { AccessibilityService service = mAccessibilityBridge.getService(); @@ -133,6 +152,9 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver if (mTouchObserver != null) { mTouchObserver.stop(); } + if (mListeningNotification) { + mAccessibilityBridge.getNotificationObserver().removeListener(this); + } } @Override @@ -169,4 +191,24 @@ public class Events extends EventEmitter implements OnKeyListener, TouchObserver } + @Override + public void onNotification(final AccessibilityEvent event, final String[] notification) { + mHandler.post(new Runnable() { + @Override + public void run() { + emit("toast", new Object[]{notification}); + } + }); + } + + @Override + public void onNotification(final AccessibilityEvent event, final Notification notification) { + mHandler.post(new Runnable() { + @Override + public void run() { + emit("notification", notification); + } + }); + + } } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java deleted file mode 100644 index 7c60b680..00000000 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/InputEventSender.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.stardust.autojs.runtime.api; - -import com.stardust.util.ScreenMetrics; - -import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Created by Stardust on 2017/7/16. - */ - -public class InputEventSender { - private DataOutputStream mDeviceFile; - private ScreenMetrics mScreenMetrics; - - - public InputEventSender(String devicePath) throws FileNotFoundException { - mDeviceFile = new DataOutputStream(new FileOutputStream(devicePath)); - } - - public InputEventSender(int i) throws FileNotFoundException { - this("/dev/input/event" + i); - } - - public InputEventSender() { - - } - - - public void sendEvent(int type, int code, int value) throws IOException { - for (int i = 0; i < 16; i++) - mDeviceFile.writeByte(0); - mDeviceFile.writeShort(type); - mDeviceFile.writeShort(code); - mDeviceFile.writeInt(value); - mDeviceFile.flush(); - } - - - public void setInputDevice(int i) throws IOException { - if (mDeviceFile != null) { - mDeviceFile.close(); - } - mDeviceFile = new DataOutputStream(new FileOutputStream("/dev/input/event" + i)); - } - - public void Touch(int x, int y) throws IOException { - TouchX(x); - TouchY(y); - } - - public void setScreenMetrics(int width, int height) { - if (mScreenMetrics == null) { - mScreenMetrics = new ScreenMetrics(); - } - mScreenMetrics.setScreenMetrics(width, height); - } - - public void TouchX(int x) throws IOException { - sendEvent(3, 53, scaleX(x)); - } - - private int scaleX(int x) { - return mScreenMetrics.scaleX(x); - } - - public void TouchY(int y) throws IOException { - sendEvent(3, 54, scaleY(y)); - } - - private int scaleY(int y) { - return mScreenMetrics.scaleY(y); - - } - - - public void close() throws IOException { - mDeviceFile.close(); - } - -} - diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java new file mode 100644 index 00000000..426f84d6 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/RootAutomator.java @@ -0,0 +1,112 @@ +package com.stardust.autojs.runtime.api; + +import android.content.Context; + +import com.stardust.pio.PFile; +import com.stardust.pio.UncheckedIOException; +import com.stardust.util.ScreenMetrics; + +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Created by Stardust on 2017/7/16. + */ + +public class RootAutomator { + + + private static final int DATA_TYPE_SLEEP = 0; + private static final int DATA_TYPE_EVENT = 1; + + private static final String ROOT_AUTOMATOR_EXECUTABLE_ASSET = "binary/root_automator"; + private DataOutputStream mTmpFileOutputStream; + private File mEventTmpFile; + private ScreenMetrics mScreenMetrics; + private String mDevicePath; + + public RootAutomator() { + try { + mEventTmpFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".auto"); + mEventTmpFile.deleteOnExit(); + mTmpFileOutputStream = new DataOutputStream(new FileOutputStream(mEventTmpFile)); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + public void sendEvent(int type, int code, int value) throws IOException { + mTmpFileOutputStream.writeByte(DATA_TYPE_EVENT); + mTmpFileOutputStream.writeShort(type); + mTmpFileOutputStream.writeShort(code); + mTmpFileOutputStream.writeInt(value); + } + + public void setInputDevice(int i) throws IOException { + mDevicePath = "/dev/input/event" + i; + } + + public void touch(int x, int y) throws IOException { + touchX(x); + touchY(y); + } + + public void setScreenMetrics(int width, int height) { + if (mScreenMetrics == null) { + mScreenMetrics = new ScreenMetrics(); + } + mScreenMetrics.setScreenMetrics(width, height); + } + + public void touchX(int x) throws IOException { + sendEvent(3, 53, scaleX(x)); + } + + private int scaleX(int x) { + return mScreenMetrics.scaleX(x); + } + + public void touchY(int y) throws IOException { + sendEvent(3, 54, scaleY(y)); + } + + public void sendSync() throws IOException { + sendEvent(0, 0, 0); + } + + private int scaleY(int y) { + return mScreenMetrics.scaleY(y); + + } + + public void sleep(int n) throws IOException { + mTmpFileOutputStream.writeByte(DATA_TYPE_SLEEP); + mTmpFileOutputStream.writeInt(n); + } + + public AbstractShell.Result writeToDevice(Context context) { + try { + mTmpFileOutputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + String executablePath = getExecutablePath(context); + return ProcessShell.execCommand(new String[]{ + "chmod 777 " + executablePath, + executablePath + " " + mEventTmpFile.getAbsolutePath() + " " + mDevicePath + }, true); + } + + public static String getExecutablePath(Context context) { + File tmp = new File(context.getCacheDir(), "root_automator"); + if (!tmp.exists()) { + PFile.copyAsset(context, ROOT_AUTOMATOR_EXECUTABLE_ASSET, tmp.getAbsolutePath()); + } + return tmp.getAbsolutePath(); + } + +} + diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java new file mode 100644 index 00000000..6e9369f3 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputDevice.java @@ -0,0 +1,8 @@ +package com.stardust.autojs.runtime.record.inputevent; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class InputDevice { +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java new file mode 100644 index 00000000..4aa0d032 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/InputEventToRootAutomatorConverter.java @@ -0,0 +1,120 @@ +package com.stardust.autojs.runtime.record.inputevent; + +import android.support.annotation.NonNull; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.stardust.util.ScreenMetrics.getDeviceScreenHeight; +import static com.stardust.util.ScreenMetrics.getDeviceScreenWidth; + +/** + * Created by Stardust on 2017/8/1. + */ + +public class InputEventToRootAutomatorConverter extends InputEventConverter { + + + private double mLastEventTime; + private StringBuilder mCode = new StringBuilder(); + private int mTouchDevice = -1; + private int mLastTouchX = -1; + private int mLastTouchY = -1; + + public InputEventToRootAutomatorConverter() { + mCode.append("var ra = new RootAutomator();\n") + .append("ra.setScreenMetrics(").append(getDeviceScreenWidth()).append(", ") + .append(getDeviceScreenHeight()).append(");\n"); + } + + + @Override + public void convertEvent(@NonNull Event event) { + if (mLastEventTime == 0) { + mLastEventTime = event.time; + } else if (event.time - mLastEventTime > 0.005) { + mCode.append("ra.sleep(").append((long) (1000L * (event.time - mLastEventTime))).append(");\n"); + mLastEventTime = event.time; + } + int device = parseDeviceNumber(event.device); + int type = (int) Long.parseLong(event.type, 16); + int code = (int) Long.parseLong(event.code, 16); + int value = (int) Long.parseLong(event.value, 16); + if (type == 3) { + if (code == 53) { + onTouchX(device, value); + return; + } + if (code == 54) { + onTouchY(device, value); + return; + } + } + checkLastTouch(); + if (device != mTouchDevice) { + return; + } + if (type == 0 && code == 0 && value == 0) { + mCode.append("ra.sendSync();\n"); + return; + } + mCode.append("ra.sendEvent("); + mCode.append(type).append(", ") + .append(code).append(", ") + .append(value).append(");\n"); + } + + private void checkLastTouch() { + if (mLastTouchX >= 0) { + mCode.append("ra.touchX(").append(mLastTouchX).append(");\n"); + mLastTouchX = -1; + } + if (mLastTouchY >= 0) { + mCode.append("ra.touchY(").append(mLastTouchY).append(");\n"); + mLastTouchY = -1; + } + } + + private void onTouchX(int device, int value) { + if (mTouchDevice == -1) { + setTouchDevice(device); + } + mLastTouchX = value; + } + + private void onTouchY(int device, int value) { + if (mTouchDevice == -1) { + setTouchDevice(device); + } + if (mLastTouchX >= 0) { + mCode.append("ra.touch(") + .append(mLastTouchX).append(", ") + .append(value).append(");\n"); + mLastTouchX = -1; + } else { + mLastTouchY = value; + } + } + + private void setTouchDevice(int i) { + mCode.append("ra.setInputDevice(").append(i).append(");\n"); + mTouchDevice = i; + } + + @Override + public String getGetEventCommand() { + return "getevent -t"; + } + + public String getCode() { + return mCode.toString(); + } + + @Override + public void stop() { + super.stop(); + mCode.append("log(ra.writeToDevice(context));"); + } + + +} diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java index d63d3d5b..92080228 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/record/inputevent/TouchRecorder.java @@ -9,7 +9,7 @@ import android.content.Context; public class TouchRecorder extends InputEventRecorder { public TouchRecorder(Context context) { - super(context, new InputEventToSendEventJsConverter()); + super(context, new InputEventToRootAutomatorConverter()); listen(); } diff --git a/autojs/src/main/res/xml/accessibility_service_config.xml b/autojs/src/main/res/xml/accessibility_service_config.xml index 84c6464a..edab932f 100644 --- a/autojs/src/main/res/xml/accessibility_service_config.xml +++ b/autojs/src/main/res/xml/accessibility_service_config.xml @@ -1,7 +1,7 @@ EVENT_TYPES = Collections.singleton(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); + + private static final String TAG = "NotificationObserver"; + private static final String[] EMPTY = new String[0]; + + private Context mContext; + private CopyOnWriteArrayList mNotificationListeners = new CopyOnWriteArrayList<>(); + + public Observer(Context context) { + mContext = context; + } + + @Override + public void onNotification(AccessibilityEvent event, String[] notification) { + for (NotificationListener listener : mNotificationListeners) { + try { + listener.onNotification(event, notification); + } catch (Exception e) { + Log.e(TAG, "Error onNotification: " + Arrays.toString(notification) + " Listener: " + listener, e); + } + } + } + + @Override + public void onNotification(AccessibilityEvent event, Notification notification) { + for (NotificationListener listener : mNotificationListeners) { + try { + listener.onNotification(event, notification); + } catch (Exception e) { + Log.e(TAG, "Error onNotification: " + notification + " Listener: " + listener, e); + } + } + } + + public void addListener(NotificationListener listener) { + mNotificationListeners.add(listener); + } + + public boolean removeListener(NotificationListener listener) { + return mNotificationListeners.remove(listener); + } + + @Override + public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) { + if (event.getParcelableData() instanceof Notification) { + Notification notification = (Notification) event.getParcelableData(); + Log.d(TAG, "onNotification: " + notification + "; " + event); + onNotification(event, notification); + } else { + List list = event.getText(); + Log.d(TAG, "onNotification: " + list + "; " + event); + if (event.getPackageName().equals(mContext.getPackageName())) { + return false; + } + if (list != null) { + onNotification(event, ArrayUtils.toStringArray(list)); + } + } + return false; + } + + @Nullable + @Override + public Set getEventTypes() { + return EVENT_TYPES; + } + } +} diff --git a/common/src/main/java/com/stardust/util/ArrayUtils.java b/common/src/main/java/com/stardust/util/ArrayUtils.java index 2d7f7c59..2e48c01e 100644 --- a/common/src/main/java/com/stardust/util/ArrayUtils.java +++ b/common/src/main/java/com/stardust/util/ArrayUtils.java @@ -1,5 +1,7 @@ package com.stardust.util; +import java.util.List; + /** * Created by Stardust on 2017/5/8. */ @@ -23,4 +25,13 @@ public class ArrayUtils { } return unbox; } + + public static String[] toStringArray(List list) { + int i = 0; + String[] str = new String[list.size()]; + for (Object o : list) { + str[i] = o == null ? null : o.toString(); + } + return str; + } }