mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-21 21:01:43 +08:00
fix(autojs): root automator not working on some device
This commit is contained in:
parent
a3ae309742
commit
b2b2362f71
@ -1,6 +1,6 @@
|
||||
module.exports = function(__runtime__, scope){
|
||||
function RootAutomator(){
|
||||
this.__ra__ = Object.create(new com.stardust.autojs.core.inputevent.RootAutomator(scope.context));
|
||||
function RootAutomator(nonBlockingForReady){
|
||||
this.__ra__ = Object.create(new com.stardust.autojs.core.inputevent.RootAutomator(scope.context, !nonBlockingForReady));
|
||||
var methods = ["sendEvent", "touch", "setScreenMetrics", "touchX", "touchY", "sendSync", "sendMtSync", "tap",
|
||||
"swipe", "press", "longPress", "touchDown", "touchUp", "touchMove", "getDefaultId", "setDefaultId", "exit"];
|
||||
for(var i = 0; i < methods.length; i++){
|
||||
|
||||
@ -1,20 +1,31 @@
|
||||
package com.stardust.autojs.core.inputevent;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.InputDevice;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/8/1.
|
||||
*/
|
||||
|
||||
public class InputDevices {
|
||||
|
||||
private static final String LOG_TAG = "InputDevices";
|
||||
|
||||
@Nullable
|
||||
public static String getTouchDeviceName() {
|
||||
InputDevice device = getTouchDevice();
|
||||
return device == null ? null : device.getName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static InputDevice getTouchDevice() {
|
||||
for (int id : InputDevice.getDeviceIds()) {
|
||||
InputDevice device = InputDevice.getDevice(id);
|
||||
Log.d(LOG_TAG, "device: " + device);
|
||||
if (supportSource(device, InputDevice.SOURCE_TOUCHSCREEN) || supportSource(device, InputDevice.SOURCE_TOUCHPAD)) {
|
||||
return device.getName();
|
||||
return device;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@ -1,37 +1,27 @@
|
||||
package com.stardust.autojs.core.inputevent;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.stardust.autojs.core.inputevent.InputDevices;
|
||||
import com.stardust.autojs.core.util.ProcessShell;
|
||||
import com.stardust.autojs.core.util.Shell;
|
||||
import com.stardust.autojs.engine.RootAutomatorEngine;
|
||||
import com.stardust.autojs.runtime.api.AbstractShell;
|
||||
import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
|
||||
import com.stardust.util.ScreenMetrics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.ABS_MT_POSITION_X;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.ABS_MT_POSITION_Y;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.ABS_MT_TOUCH_MAJOR;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.ABS_MT_TRACKING_ID;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.BTN_TOOL_FINGER;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.BTN_TOUCH;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.EV_ABS;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.EV_KEY;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.EV_SYN;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.SYN_MT_REPORT;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.SYN_REPORT;
|
||||
import static com.stardust.autojs.core.inputevent.InputEventCodes.*;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/7/16.
|
||||
*/
|
||||
|
||||
public class RootAutomator {
|
||||
public class RootAutomator implements Shell.Callback {
|
||||
|
||||
private static final String LOG_TAG = "RootAutomator";
|
||||
|
||||
@ -43,22 +33,50 @@ public class RootAutomator {
|
||||
|
||||
@Nullable
|
||||
private ScreenMetrics mScreenMetrics;
|
||||
private AbstractShell mShell;
|
||||
private int mDefaultId = 1;
|
||||
private Shell mShell;
|
||||
private int mDefaultId = 0;
|
||||
private AtomicInteger mTracingId = new AtomicInteger(1);
|
||||
private SparseIntArray mSlotIdMap = new SparseIntArray();
|
||||
private final Object mReadyLock = new Object();
|
||||
private volatile boolean mReady = false;
|
||||
private final Context mContext;
|
||||
|
||||
public RootAutomator(Context context) {
|
||||
mShell = new ProcessShell(true);
|
||||
String path = RootAutomatorEngine.getExecutablePath(context);
|
||||
String deviceNameOrPath = RootAutomatorEngine.getDeviceNameOrPath(context, InputDevices.getTouchDeviceName());
|
||||
mShell.exec("chmod 777 " + path);
|
||||
mShell.exec(path + " -d " + deviceNameOrPath);
|
||||
public RootAutomator(Context context, boolean waitForReady) throws IOException {
|
||||
mContext = context;
|
||||
mShell = new Shell(true);
|
||||
mShell.setCallback(this);
|
||||
if(waitForReady){
|
||||
waitForReady();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendEvent(int type, int code, int value) throws IOException {
|
||||
waitForReady();
|
||||
sendEventInternal(type, code, value);
|
||||
}
|
||||
|
||||
private void sendEventInternal(int type, int code, int value) {
|
||||
mShell.exec(type + " " + code + " " + value);
|
||||
}
|
||||
|
||||
private void waitForReady() throws IOException {
|
||||
if(mReady){
|
||||
return;
|
||||
}
|
||||
synchronized (mReadyLock){
|
||||
if(mReady){
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mReadyLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
exit();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void touch(int x, int y) throws IOException {
|
||||
touchX(x);
|
||||
touchY(y);
|
||||
@ -150,11 +168,28 @@ public class RootAutomator {
|
||||
}
|
||||
|
||||
public void touchDown(int x, int y, int id) throws IOException {
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, id);
|
||||
if(mSlotIdMap.size() == 0){
|
||||
touchDown0(x, y, id);
|
||||
return;
|
||||
}
|
||||
int slotId = mSlotIdMap.size();
|
||||
mSlotIdMap.put(id, slotId);
|
||||
sendEvent(EV_ABS, ABS_MT_SLOT, slotId);
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, mTracingId.getAndIncrement());
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_X, scaleX(x));
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_Y, scaleY(y));
|
||||
sendEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
|
||||
sendEvent(EV_SYN, SYN_REPORT, 0x00000000);
|
||||
}
|
||||
|
||||
private void touchDown0(int x, int y, int id) throws IOException {
|
||||
mSlotIdMap.put(id, 0);
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, mTracingId.getAndIncrement());
|
||||
sendEvent(EV_KEY, BTN_TOUCH, 0x00000001);
|
||||
sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000001);
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_X, scaleX(x));
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_Y, scaleY(y));
|
||||
//sendEvent(EV_ABS, ABS_MT_PRESSURE, 200);
|
||||
sendEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
|
||||
sendEvent(EV_SYN, SYN_REPORT, 0x00000000);
|
||||
}
|
||||
@ -164,9 +199,20 @@ public class RootAutomator {
|
||||
}
|
||||
|
||||
public void touchUp(int id) throws IOException {
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, id);
|
||||
sendEvent(EV_KEY, BTN_TOUCH, 0x00000000);
|
||||
sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000000);
|
||||
int slotId ;
|
||||
int i = mSlotIdMap.indexOfKey(id);
|
||||
if( i < 0){
|
||||
slotId = 0;
|
||||
}else {
|
||||
slotId = mSlotIdMap.valueAt(i);
|
||||
mSlotIdMap.removeAt(i);
|
||||
}
|
||||
sendEvent(EV_ABS, ABS_MT_SLOT, slotId);
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, 0xffffffff);
|
||||
if(mSlotIdMap.size() == 0){
|
||||
sendEvent(EV_KEY, BTN_TOUCH, 0x00000000);
|
||||
sendEvent(EV_KEY, BTN_TOOL_FINGER, 0x00000000);
|
||||
}
|
||||
sendEvent(EV_SYN, SYN_REPORT, 0x00000000);
|
||||
}
|
||||
|
||||
@ -175,7 +221,9 @@ public class RootAutomator {
|
||||
}
|
||||
|
||||
public void touchMove(int x, int y, int id) throws IOException {
|
||||
sendEvent(EV_ABS, ABS_MT_TRACKING_ID, id);
|
||||
int slotId = mSlotIdMap.get(id, 0);
|
||||
sendEvent(EV_ABS, ABS_MT_SLOT, slotId);
|
||||
sendEvent(EV_ABS, ABS_MT_TOUCH_MAJOR, 5);
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_X, scaleX(x));
|
||||
sendEvent(EV_ABS, ABS_MT_POSITION_Y, scaleY(y));
|
||||
sendEvent(EV_SYN, SYN_REPORT, 0x00000000);
|
||||
@ -207,7 +255,8 @@ public class RootAutomator {
|
||||
}
|
||||
|
||||
public void exit() throws IOException {
|
||||
sendEvent(0xffff, 0xffff, 0xefefefef);
|
||||
sleep(1);
|
||||
sendEventInternal(0xffff, 0xffff, 0xefefefef);
|
||||
mShell.exec("exit");
|
||||
mShell.exec("exit");
|
||||
mShell.exec("exit");
|
||||
@ -217,5 +266,33 @@ public class RootAutomator {
|
||||
mShell.exit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOutput(String str) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewLine(String line) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitialized() {
|
||||
String path = RootAutomatorEngine.getExecutablePath(mContext);
|
||||
String deviceNameOrPath = RootAutomatorEngine.getDeviceNameOrPath(mContext, InputDevices.getTouchDeviceName());
|
||||
Log.d(LOG_TAG, "deviceNameOrPath: " + deviceNameOrPath);
|
||||
mShell.exec("chmod 777 " + path);
|
||||
String command = path + " -d " + deviceNameOrPath;
|
||||
mShell.exec(command);
|
||||
synchronized (mReadyLock){
|
||||
Log.d(LOG_TAG, "notify ready");
|
||||
mReady = true;
|
||||
mReadyLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupted(InterruptedException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ public class Shell extends AbstractShell {
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean DEBUG = true;
|
||||
private static final String TAG = "Shell";
|
||||
|
||||
private volatile TermSession mTermSession;
|
||||
@ -97,16 +98,13 @@ public class Shell extends AbstractShell {
|
||||
@Override
|
||||
protected void init(final String initialCommand) {
|
||||
Handler uiHandler = new Handler(mContext.getMainLooper());
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TermSettings settings = new TermSettings(mContext.getResources(), PreferenceManager.getDefaultSharedPreferences(mContext));
|
||||
try {
|
||||
mTermSession = new MyShellTermSession(settings, initialCommand);
|
||||
mTermSession.initializeEmulator(1024, 40);
|
||||
} catch (IOException e) {
|
||||
mInitException = new UncheckedIOException(e);
|
||||
}
|
||||
uiHandler.post(() -> {
|
||||
TermSettings settings = new TermSettings(mContext.getResources(), PreferenceManager.getDefaultSharedPreferences(mContext));
|
||||
try {
|
||||
mTermSession = new MyShellTermSession(settings, initialCommand);
|
||||
mTermSession.initializeEmulator(1024, 40);
|
||||
} catch (IOException e) {
|
||||
mInitException = new UncheckedIOException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -126,12 +124,21 @@ public class Shell extends AbstractShell {
|
||||
|
||||
private void ensureInitialized() {
|
||||
if (mTermSession == null) {
|
||||
logDebug("ensureInitialized: not init");
|
||||
checkInitException();
|
||||
waitInitialization();
|
||||
if (mTermSession == null) {
|
||||
checkInitException();
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}else {
|
||||
logDebug("ensureInitialized: init");
|
||||
}
|
||||
}
|
||||
|
||||
private void logDebug(String log){
|
||||
if(DEBUG){
|
||||
Log.d(TAG, log);
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,11 +149,14 @@ public class Shell extends AbstractShell {
|
||||
}
|
||||
|
||||
private void waitInitialization() {
|
||||
if (mInitialized)
|
||||
throw new IllegalStateException("already initialized");
|
||||
synchronized (mInitLock) {
|
||||
if(mInitialized){
|
||||
return;
|
||||
}
|
||||
logDebug("waitInitialization: enter");
|
||||
try {
|
||||
mInitLock.wait();
|
||||
logDebug("waitInitialization: exit");
|
||||
} catch (InterruptedException e) {
|
||||
onInterrupted(e);
|
||||
}
|
||||
@ -209,33 +219,25 @@ public class Shell extends AbstractShell {
|
||||
}
|
||||
|
||||
private void startReadingThread() {
|
||||
mReadingThread = new ThreadCompat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String line;
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()
|
||||
&& (line = mBufferedReader.readLine()) != null) {
|
||||
onNewLine(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
mReadingThread = new ThreadCompat(() -> {
|
||||
String line;
|
||||
try {
|
||||
while (!Thread.currentThread().isInterrupted()
|
||||
&& (line = mBufferedReader.readLine()) != null) {
|
||||
onNewLine(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
mReadingThread.start();
|
||||
}
|
||||
|
||||
private void onNewLine(String line) {
|
||||
//Log.d(TAG, line);
|
||||
logDebug("onNewLine: " + line);
|
||||
if (!mInitialized) {
|
||||
if (isRoot() && line.endsWith(" $ su")) {
|
||||
notifyInitialized();
|
||||
return;
|
||||
}
|
||||
if (!isRoot() && line.endsWith(" $ sh")) {
|
||||
notifyInitialized();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mCallback != null) {
|
||||
@ -246,13 +248,23 @@ public class Shell extends AbstractShell {
|
||||
}
|
||||
}
|
||||
|
||||
private void onOutput(String str){
|
||||
logDebug("onOutput: " + str);
|
||||
if (!mInitialized) {
|
||||
if (isRoot() && str.endsWith(":/ # ")) {
|
||||
notifyInitialized();
|
||||
}
|
||||
}
|
||||
if (mCallback != null) {
|
||||
mCallback.onOutput(str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void processInput(byte[] data, int offset, int count) {
|
||||
try {
|
||||
if (mCallback != null) {
|
||||
mCallback.onOutput(new String(data, offset, count));
|
||||
}
|
||||
onOutput(new String(data, offset, count));
|
||||
mOutputStream.write(data, offset, count);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
@ -268,6 +280,7 @@ public class Shell extends AbstractShell {
|
||||
}
|
||||
|
||||
private void notifyInitialized() {
|
||||
logDebug("notifyInitialized");
|
||||
mInitialized = true;
|
||||
synchronized (mInitLock) {
|
||||
mInitLock.notifyAll();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user