no message

This commit is contained in:
wanjian
2017-04-04 23:36:22 +08:00
parent 6b4719c5b2
commit ccda852879
20 changed files with 694 additions and 24 deletions

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,8 @@
package android.view;
/**
* Created by wanjian on 2017/4/4.
*/
public interface DisplayInfo {
}

View File

@@ -0,0 +1,8 @@
package android.view;
/**
* Created by wanjian on 2017/4/4.
*/
public interface IRotationWatcher {
}

View File

@@ -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;
}
}
}

View 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));
}
}

View File

@@ -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");
}
}

View File

@@ -0,0 +1,5 @@
package com.wanjian.puppet;
public interface VirtualDisplay {
void release();
}

View File

@@ -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();
}