no message
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package android.hardware.display;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IDisplayManager {
|
||||
DisplayInfo getDisplayInfo(int i);
|
||||
|
||||
abstract class Stub {
|
||||
public static IDisplayManager asInterface(IBinder invoke) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface DisplayInfo {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package android.view;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IRotationWatcher {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package android.view;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public interface IWindowManager {
|
||||
void getInitialDisplaySize(int i, Point displaySize);
|
||||
|
||||
int getRotation();
|
||||
|
||||
void getRealDisplaySize(Point displaySize);
|
||||
|
||||
abstract class Stub {
|
||||
|
||||
public static IWindowManager asInterface(IBinder invoke) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
279
shareandcontrollib/src/main/java/com/wanjian/puppet/Main.java
Normal file
279
shareandcontrollib/src/main/java/com/wanjian/puppet/Main.java
Normal file
@@ -0,0 +1,279 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.net.LocalServerSocket;
|
||||
import android.net.LocalSocket;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.view.InputDeviceCompat;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Created by wanjian on 2017/4/4.
|
||||
*/
|
||||
|
||||
public class Main {
|
||||
|
||||
private static InputManager im;
|
||||
private static Method injectInputEventMethod;
|
||||
private static long downTime;
|
||||
|
||||
private static IWindowManager wm;
|
||||
|
||||
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
|
||||
|
||||
System.out.println("start!");
|
||||
LocalServerSocket serverSocket = new LocalServerSocket("puppet-ver1");
|
||||
|
||||
init();
|
||||
|
||||
while (true) {
|
||||
System.out.println("listen.....");
|
||||
LocalSocket socket = serverSocket.accept();
|
||||
acceptConnect(socket);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void init() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
|
||||
|
||||
System.out.println("init...");
|
||||
Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
wm = IWindowManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
|
||||
im = (InputManager) InputManager.class.getDeclaredMethod("getInstance", new Class[0]).invoke(null, new Object[0]);
|
||||
MotionEvent.class.getDeclaredMethod("obtain", new Class[0]).setAccessible(true);
|
||||
injectInputEventMethod = InputManager.class.getMethod("injectInputEvent", new Class[]{InputEvent.class, Integer.TYPE});
|
||||
|
||||
System.out.println("init finished...");
|
||||
}
|
||||
|
||||
private static void acceptConnect(LocalSocket socket) {
|
||||
System.out.println("accepted...");
|
||||
read(socket);
|
||||
write(socket);
|
||||
}
|
||||
|
||||
private static void write(final LocalSocket socket) {
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
final int VERSION = 2;
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
|
||||
while (true) {
|
||||
Bitmap bitmap = screenshot();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 60, byteArrayOutputStream);
|
||||
|
||||
outputStream.write(2);
|
||||
writeInt(outputStream, byteArrayOutputStream.size());
|
||||
outputStream.write(byteArrayOutputStream.toByteArray());
|
||||
outputStream.flush();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private static void read(final LocalSocket socket) {
|
||||
|
||||
new Thread() {
|
||||
private final String DOWN = "DOWN";
|
||||
private final String MOVE = "MOVE";
|
||||
private final String UP = "UP";
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
while (true) {
|
||||
String line;
|
||||
try {
|
||||
line = reader.readLine();
|
||||
if (line == null) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (line.startsWith(DOWN)) {
|
||||
hanlerDown(line.substring(DOWN.length()));
|
||||
// hanlerUp(line.substring(DOWN.length()));
|
||||
} else if (line.startsWith(MOVE)) {
|
||||
hanlerMove(line.substring(MOVE.length()));
|
||||
} else if (line.startsWith(UP)) {
|
||||
hanlerUp(line.substring(UP.length()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private static void hanlerUp(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchUp(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void hanlerMove(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchMove(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void hanlerDown(String line) {
|
||||
Point point = getXY(line);
|
||||
if (point != null) {
|
||||
try {
|
||||
touchDown(point.x, point.y);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Point getXY(String nums) {
|
||||
try {
|
||||
Point point = SurfaceControlVirtualDisplayFactory.getCurrentDisplaySize(false);
|
||||
String[] s = nums.split("#");
|
||||
float scaleX = Float.parseFloat(s[0]);
|
||||
float scaleY = Float.parseFloat(s[1]);
|
||||
point.x *= scaleX;
|
||||
point.y *= scaleY;
|
||||
System.out.println("point x=" + point.x + " y=" + point.y);
|
||||
return point;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static void writeInt(OutputStream outputStream, int v) throws IOException {
|
||||
outputStream.write(v >> 24);
|
||||
outputStream.write(v >> 16);
|
||||
outputStream.write(v >> 8);
|
||||
outputStream.write(v);
|
||||
}
|
||||
|
||||
public static Bitmap screenshot() throws Exception {
|
||||
|
||||
String surfaceClassName;
|
||||
Point size = SurfaceControlVirtualDisplayFactory.getCurrentDisplaySize(false);
|
||||
if (Build.VERSION.SDK_INT <= 17) {
|
||||
surfaceClassName = "android.view.Surface";
|
||||
} else {
|
||||
surfaceClassName = "android.view.SurfaceControl";
|
||||
}
|
||||
Bitmap b = (Bitmap) Class.forName(surfaceClassName).getDeclaredMethod("screenshot", new Class[]{Integer.TYPE, Integer.TYPE}).invoke(null, new Object[]{Integer.valueOf(size.x), Integer.valueOf(size.y)});
|
||||
int rotation = wm.getRotation();
|
||||
if (rotation == 0) {
|
||||
return b;
|
||||
}
|
||||
Matrix m = new Matrix();
|
||||
if (rotation == 1) {
|
||||
m.postRotate(-90.0f);
|
||||
} else if (rotation == 2) {
|
||||
m.postRotate(-180.0f);
|
||||
} else if (rotation == 3) {
|
||||
m.postRotate(-270.0f);
|
||||
}
|
||||
return Bitmap.createBitmap(b, 0, 0, size.x, size.y, m, false);
|
||||
}
|
||||
|
||||
|
||||
private static void back() throws InvocationTargetException, IllegalAccessException {
|
||||
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 4, false);
|
||||
}
|
||||
|
||||
|
||||
private static void touchUp(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("up " + clientX + " " + clientY);
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 1, downTime, SystemClock.uptimeMillis(), clientX, clientY, 1.0f);
|
||||
}
|
||||
|
||||
private static void touchMove(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("move " + clientX + " " + clientY);
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 2, downTime, SystemClock.uptimeMillis(), clientX, clientY, 1.0f);
|
||||
}
|
||||
|
||||
private static void touchDown(float clientX, float clientY) throws InvocationTargetException, IllegalAccessException {
|
||||
System.out.println("down " + clientX + " " + clientY);
|
||||
downTime = SystemClock.uptimeMillis();
|
||||
injectMotionEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_TOUCHSCREEN, 0, downTime, downTime, clientX, clientY, 1.0f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static void pressHome() throws InvocationTargetException, IllegalAccessException {
|
||||
sendKeyEvent(im, injectInputEventMethod, InputDeviceCompat.SOURCE_KEYBOARD, 3, false);
|
||||
}
|
||||
|
||||
|
||||
private static void injectMotionEvent(InputManager im, Method injectInputEventMethod, int inputSource, int action, long downTime, long eventTime, float x, float y, float pressure) throws InvocationTargetException, IllegalAccessException {
|
||||
MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, pressure, 1.0f, 0, 1.0f, 1.0f, 0, 0);
|
||||
event.setSource(inputSource);
|
||||
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
|
||||
}
|
||||
|
||||
private static void injectKeyEvent(InputManager im, Method injectInputEventMethod, KeyEvent event) throws InvocationTargetException, IllegalAccessException {
|
||||
injectInputEventMethod.invoke(im, new Object[]{event, Integer.valueOf(0)});
|
||||
}
|
||||
|
||||
|
||||
private static void sendKeyEvent(InputManager im, Method injectInputEventMethod, int inputSource, int keyCode, boolean shift) throws InvocationTargetException, IllegalAccessException {
|
||||
long now = SystemClock.uptimeMillis();
|
||||
int meta = shift ? 1 : 0;
|
||||
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 0, keyCode, 0, meta, -1, 0, 0, inputSource));
|
||||
injectKeyEvent(im, injectInputEventMethod, new KeyEvent(now, now, 1, keyCode, 0, meta, -1, 0, 0, inputSource));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.IDisplayManager;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IRotationWatcher;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.IWindowManager.Stub;
|
||||
import android.view.Surface;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class SurfaceControlVirtualDisplayFactory implements VirtualDisplayFactory {
|
||||
private static final String LOGTAG = "SCVDF";
|
||||
Rect displayRect;
|
||||
Point displaySize = getCurrentDisplaySize();
|
||||
|
||||
public static Point getCurrentDisplaySize() {
|
||||
return getCurrentDisplaySize(true);
|
||||
}
|
||||
|
||||
public static Point getCurrentDisplaySize(boolean rotate) {
|
||||
try {
|
||||
Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
Point displaySize = new Point();
|
||||
IWindowManager wm;
|
||||
int rotation;
|
||||
if (VERSION.SDK_INT >= 18) {
|
||||
wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
wm.getInitialDisplaySize(0, displaySize);
|
||||
rotation = wm.getRotation();
|
||||
} else if (VERSION.SDK_INT == 17) {
|
||||
DisplayInfo di = IDisplayManager.Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"display"})).getDisplayInfo(0);
|
||||
displaySize.x = ((Integer) DisplayInfo.class.getDeclaredField("logicalWidth").get(di)).intValue();
|
||||
displaySize.y = ((Integer) DisplayInfo.class.getDeclaredField("logicalHeight").get(di)).intValue();
|
||||
rotation = ((Integer) DisplayInfo.class.getDeclaredField("rotation").get(di)).intValue();
|
||||
} else {
|
||||
wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
wm.getRealDisplaySize(displaySize);
|
||||
rotation = wm.getRotation();
|
||||
}
|
||||
if ((rotate && rotation == 1) || rotation == 3) {
|
||||
int swap = displaySize.x;
|
||||
displaySize.x = displaySize.y;
|
||||
displaySize.y = swap;
|
||||
}
|
||||
return displaySize;
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public VirtualDisplay createVirtualDisplay(String name, int width, int height, int dpi, int flags, Surface surface, Handler handler) {
|
||||
try {
|
||||
Class surfaceControlClass = Class.forName("android.view.SurfaceControl");
|
||||
Class cls = surfaceControlClass;
|
||||
final IBinder token = (IBinder) cls.getDeclaredMethod("createDisplay", new Class[]{String.class, Boolean.TYPE}).invoke(null, new Object[]{name, Boolean.valueOf(false)});
|
||||
cls = surfaceControlClass;
|
||||
Method setDisplaySurfaceMethod = cls.getDeclaredMethod("setDisplaySurface", new Class[]{IBinder.class, Surface.class});
|
||||
cls = surfaceControlClass;
|
||||
final Method setDisplayProjectionMethod = cls.getDeclaredMethod("setDisplayProjection", new Class[]{IBinder.class, Integer.TYPE, Rect.class, Rect.class});
|
||||
cls = surfaceControlClass;
|
||||
Method setDisplayLayerStackMethod = cls.getDeclaredMethod("setDisplayLayerStack", new Class[]{IBinder.class, Integer.TYPE});
|
||||
final Method openTransactionMethod = surfaceControlClass.getDeclaredMethod("openTransaction", new Class[0]);
|
||||
final Method closeTransactionMethod = surfaceControlClass.getDeclaredMethod("closeTransaction", new Class[0]);
|
||||
final Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
|
||||
this.displayRect = new Rect(0, 0, width, height);
|
||||
Rect layerStackRect = new Rect(0, 0, this.displaySize.x, this.displaySize.y);
|
||||
openTransactionMethod.invoke(null, new Object[0]);
|
||||
setDisplaySurfaceMethod.invoke(null, new Object[]{token, surface});
|
||||
setDisplayProjectionMethod.invoke(null, new Object[]{token, Integer.valueOf(0), layerStackRect, this.displayRect});
|
||||
setDisplayLayerStackMethod.invoke(null, new Object[]{token, Integer.valueOf(0)});
|
||||
closeTransactionMethod.invoke(null, new Object[0]);
|
||||
cls = surfaceControlClass;
|
||||
final Method destroyDisplayMethod = cls.getDeclaredMethod("destroyDisplay", new Class[]{IBinder.class});
|
||||
return new VirtualDisplay() {
|
||||
IRotationWatcher watcher;
|
||||
IWindowManager wm = Stub.asInterface((IBinder) getServiceMethod.invoke(null, new Object[]{"window"}));
|
||||
|
||||
public void release() {
|
||||
Log.i(SurfaceControlVirtualDisplayFactory.LOGTAG, "VirtualDisplay released");
|
||||
this.wm = null;
|
||||
this.watcher = null;
|
||||
try {
|
||||
destroyDisplayMethod.invoke(null, new Object[]{token});
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Point getDisplaySize() {
|
||||
return new Point(this.displaySize);
|
||||
}
|
||||
|
||||
public Rect getDisplayRect() {
|
||||
return this.displayRect;
|
||||
}
|
||||
|
||||
public void release() {
|
||||
Log.i(LOGTAG, "factory released");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
public interface VirtualDisplay {
|
||||
void release();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.wanjian.puppet;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.wanjian.puppet.VirtualDisplay;
|
||||
|
||||
public interface VirtualDisplayFactory {
|
||||
VirtualDisplay createVirtualDisplay(String str, int i, int i2, int i3, int i4, Surface surface, Handler handler);
|
||||
|
||||
void release();
|
||||
}
|
||||
Reference in New Issue
Block a user