Implement framework wrappers separately

Move the DeviceUtil internal static classes to public classes, in a
separate package (".wrappers").

This paves the way to implement InputManager properly.
This commit is contained in:
Romain Vimont 2017-12-13 17:02:39 +01:00
parent 39fd6ce518
commit 1a71c4ab1d
5 changed files with 109 additions and 93 deletions

View file

@ -22,6 +22,9 @@ SRC := com/genymobile/scrcpy/ScrCpyServer.java \
com/genymobile/scrcpy/ScreenInfo.java \ com/genymobile/scrcpy/ScreenInfo.java \
com/genymobile/scrcpy/ScreenStreamer.java \ com/genymobile/scrcpy/ScreenStreamer.java \
com/genymobile/scrcpy/ScreenStreamerSession.java \ com/genymobile/scrcpy/ScreenStreamerSession.java \
com/genymobile/scrcpy/wrappers/DisplayManager.java \
com/genymobile/scrcpy/wrappers/ServiceManager.java \
com/genymobile/scrcpy/wrappers/WindowManager.java \
JAR := scrcpy-server.jar JAR := scrcpy-server.jar
MAIN := com.genymobile.scrcpy.ScrCpyServer MAIN := com.genymobile.scrcpy.ScrCpyServer

View file

@ -1,11 +1,9 @@
package com.genymobile.scrcpy; package com.genymobile.scrcpy;
import android.os.Build; import android.os.Build;
import android.os.IBinder;
import android.os.IInterface;
import android.view.IRotationWatcher; import android.view.IRotationWatcher;
import java.lang.reflect.Method; import com.genymobile.scrcpy.wrappers.ServiceManager;
public class DeviceUtil { public class DeviceUtil {
@ -22,94 +20,4 @@ public class DeviceUtil {
public static String getDeviceName() { public static String getDeviceName() {
return Build.MODEL; return Build.MODEL;
} }
private static class ServiceManager {
private Method getServiceMethod;
public ServiceManager() {
try {
getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);
} catch (Exception e) {
throw new AssertionError(e);
}
}
private IInterface getService(String service, String type) {
try {
IBinder binder = (IBinder) getServiceMethod.invoke(null, service);
Method asInterfaceMethod = Class.forName(type + "$Stub").getMethod("asInterface", IBinder.class);
return (IInterface) asInterfaceMethod.invoke(null, binder);
} catch (Exception e) {
throw new AssertionError(e);
}
}
public WindowManager getWindowManager() {
return new WindowManager(getService("window", "android.view.IWindowManager"));
}
public DisplayManager getDisplayManager() {
return new DisplayManager(getService("display", "android.hardware.display.IDisplayManager"));
}
}
private static class WindowManager {
private IInterface manager;
public WindowManager(IInterface manager) {
this.manager = manager;
}
public int getRotation() {
try {
Class<?> cls = manager.getClass();
try {
return (Integer) manager.getClass().getMethod("getRotation").invoke(manager);
} catch (NoSuchMethodException e) {
// method changed since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/8ee7285128c3843401d4c4d0412cd66e86ba49e3%5E%21/#F2
return (Integer) cls.getMethod("getDefaultDisplayRotation").invoke(manager);
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
try {
Class<?> cls = manager.getClass();
try {
cls.getMethod("watchRotation", IRotationWatcher.class).invoke(manager, rotationWatcher);
} catch (NoSuchMethodException e) {
// display parameter added since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/35fa3c26adcb5f6577849fd0df5228b1f67cf2c6%5E%21/#F1
cls.getMethod("watchRotation", IRotationWatcher.class, int.class).invoke(manager, rotationWatcher, 0);
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
private static class DisplayManager {
private IInterface manager;
public DisplayManager(IInterface manager) {
this.manager = manager;
}
public ScreenInfo getScreenInfo() {
try {
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, 0);
Class<?> cls = displayInfo.getClass();
// width and height do not depend on the rotation
int width = (Integer) cls.getMethod("getNaturalWidth").invoke(displayInfo);
int height = (Integer) cls.getMethod("getNaturalHeight").invoke(displayInfo);
int rotation = cls.getDeclaredField("rotation").getInt(displayInfo);
return new ScreenInfo(width, height, rotation);
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
} }

View file

@ -0,0 +1,27 @@
package com.genymobile.scrcpy.wrappers;
import android.os.IInterface;
import com.genymobile.scrcpy.ScreenInfo;
public class DisplayManager {
private final IInterface manager;
public DisplayManager(IInterface manager) {
this.manager = manager;
}
public ScreenInfo getScreenInfo() {
try {
Object displayInfo = manager.getClass().getMethod("getDisplayInfo", int.class).invoke(manager, 0);
Class<?> cls = displayInfo.getClass();
// width and height do not depend on the rotation
int width = (Integer) cls.getMethod("getNaturalWidth").invoke(displayInfo);
int height = (Integer) cls.getMethod("getNaturalHeight").invoke(displayInfo);
int rotation = cls.getDeclaredField("rotation").getInt(displayInfo);
return new ScreenInfo(width, height, rotation);
} catch (Exception e) {
throw new AssertionError(e);
}
}
}

View file

@ -0,0 +1,36 @@
package com.genymobile.scrcpy.wrappers;
import android.os.IBinder;
import android.os.IInterface;
import java.lang.reflect.Method;
public class ServiceManager {
private final Method getServiceMethod;
public ServiceManager() {
try {
getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class);
} catch (Exception e) {
throw new AssertionError(e);
}
}
private IInterface getService(String service, String type) {
try {
IBinder binder = (IBinder) getServiceMethod.invoke(null, service);
Method asInterfaceMethod = Class.forName(type + "$Stub").getMethod("asInterface", IBinder.class);
return (IInterface) asInterfaceMethod.invoke(null, binder);
} catch (Exception e) {
throw new AssertionError(e);
}
}
public WindowManager getWindowManager() {
return new WindowManager(getService("window", "android.view.IWindowManager"));
}
public DisplayManager getDisplayManager() {
return new DisplayManager(getService("display", "android.hardware.display.IDisplayManager"));
}
}

View file

@ -0,0 +1,42 @@
package com.genymobile.scrcpy.wrappers;
import android.os.IInterface;
import android.view.IRotationWatcher;
public class WindowManager {
private final IInterface manager;
public WindowManager(IInterface manager) {
this.manager = manager;
}
public int getRotation() {
try {
Class<?> cls = manager.getClass();
try {
return (Integer) manager.getClass().getMethod("getRotation").invoke(manager);
} catch (NoSuchMethodException e) {
// method changed since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/8ee7285128c3843401d4c4d0412cd66e86ba49e3%5E%21/#F2
return (Integer) cls.getMethod("getDefaultDisplayRotation").invoke(manager);
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
public void registerRotationWatcher(IRotationWatcher rotationWatcher) {
try {
Class<?> cls = manager.getClass();
try {
cls.getMethod("watchRotation", IRotationWatcher.class).invoke(manager, rotationWatcher);
} catch (NoSuchMethodException e) {
// display parameter added since this commit:
// https://android.googlesource.com/platform/frameworks/base/+/35fa3c26adcb5f6577849fd0df5228b1f67cf2c6%5E%21/#F1
cls.getMethod("watchRotation", IRotationWatcher.class, int.class).invoke(manager, rotationWatcher, 0);
}
} catch (Exception e) {
throw new AssertionError(e);
}
}
}