mirror of https://github.com/Genymobile/scrcpy
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
8.7 KiB
Java
209 lines
8.7 KiB
Java
package com.genymobile.scrcpy.wrappers;
|
|
|
|
import com.genymobile.scrcpy.Ln;
|
|
|
|
import android.annotation.TargetApi;
|
|
import android.os.IInterface;
|
|
import android.view.IDisplayFoldListener;
|
|
import android.view.IRotationWatcher;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
public final class WindowManager {
|
|
private final IInterface manager;
|
|
private Method getRotationMethod;
|
|
|
|
private Method freezeDisplayRotationMethod;
|
|
private int freezeDisplayRotationMethodVersion;
|
|
|
|
private Method isDisplayRotationFrozenMethod;
|
|
private int isDisplayRotationFrozenMethodVersion;
|
|
|
|
private Method thawDisplayRotationMethod;
|
|
private int thawDisplayRotationMethodVersion;
|
|
|
|
static WindowManager create() {
|
|
IInterface manager = ServiceManager.getService("window", "android.view.IWindowManager");
|
|
return new WindowManager(manager);
|
|
}
|
|
|
|
private WindowManager(IInterface manager) {
|
|
this.manager = manager;
|
|
}
|
|
|
|
private Method getGetRotationMethod() throws NoSuchMethodException {
|
|
if (getRotationMethod == null) {
|
|
Class<?> cls = manager.getClass();
|
|
try {
|
|
// method changed since this commit:
|
|
// https://android.googlesource.com/platform/frameworks/base/+/8ee7285128c3843401d4c4d0412cd66e86ba49e3%5E%21/#F2
|
|
getRotationMethod = cls.getMethod("getDefaultDisplayRotation");
|
|
} catch (NoSuchMethodException e) {
|
|
// old version
|
|
getRotationMethod = cls.getMethod("getRotation");
|
|
}
|
|
}
|
|
return getRotationMethod;
|
|
}
|
|
|
|
private Method getFreezeDisplayRotationMethod() throws NoSuchMethodException {
|
|
if (freezeDisplayRotationMethod == null) {
|
|
try {
|
|
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeRotation", int.class);
|
|
freezeDisplayRotationMethodVersion = 0;
|
|
} catch (NoSuchMethodException e) {
|
|
try {
|
|
// New method added by this commit:
|
|
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
|
|
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class);
|
|
freezeDisplayRotationMethodVersion = 1;
|
|
} catch (NoSuchMethodException e1) {
|
|
// Android 15 preview and 14 QPR3 Beta added a String caller parameter for debugging:
|
|
// <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
|
|
freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class, String.class);
|
|
freezeDisplayRotationMethodVersion = 2;
|
|
}
|
|
}
|
|
}
|
|
return freezeDisplayRotationMethod;
|
|
}
|
|
|
|
private Method getIsDisplayRotationFrozenMethod() throws NoSuchMethodException {
|
|
if (isDisplayRotationFrozenMethod == null) {
|
|
try {
|
|
isDisplayRotationFrozenMethod = manager.getClass().getMethod("isRotationFrozen");
|
|
isDisplayRotationFrozenMethodVersion = 0;
|
|
} catch (NoSuchMethodException e) {
|
|
// New method added by this commit:
|
|
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
|
|
isDisplayRotationFrozenMethod = manager.getClass().getMethod("isDisplayRotationFrozen", int.class);
|
|
isDisplayRotationFrozenMethodVersion = 1;
|
|
}
|
|
}
|
|
return isDisplayRotationFrozenMethod;
|
|
}
|
|
|
|
private Method getThawDisplayRotationMethod() throws NoSuchMethodException {
|
|
if (thawDisplayRotationMethod == null) {
|
|
try {
|
|
thawDisplayRotationMethod = manager.getClass().getMethod("thawRotation");
|
|
thawDisplayRotationMethodVersion = 0;
|
|
} catch (NoSuchMethodException e) {
|
|
try {
|
|
// New method added by this commit:
|
|
// <https://android.googlesource.com/platform/frameworks/base/+/90c9005e687aa0f63f1ac391adc1e8878ab31759%5E%21/>
|
|
thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class);
|
|
thawDisplayRotationMethodVersion = 1;
|
|
} catch (NoSuchMethodException e1) {
|
|
// Android 15 preview and 14 QPR3 Beta added a String caller parameter for debugging:
|
|
// <https://android.googlesource.com/platform/frameworks/base/+/670fb7f5c0d23cf51ead25538bcb017e03ed73ac%5E%21/>
|
|
thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class, String.class);
|
|
thawDisplayRotationMethodVersion = 2;
|
|
}
|
|
}
|
|
}
|
|
return thawDisplayRotationMethod;
|
|
}
|
|
|
|
public int getRotation() {
|
|
try {
|
|
Method method = getGetRotationMethod();
|
|
return (int) method.invoke(manager);
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public void freezeRotation(int displayId, int rotation) {
|
|
try {
|
|
Method method = getFreezeDisplayRotationMethod();
|
|
switch (freezeDisplayRotationMethodVersion) {
|
|
case 0:
|
|
if (displayId != 0) {
|
|
Ln.e("Secondary display rotation not supported on this device");
|
|
return;
|
|
}
|
|
method.invoke(manager, rotation);
|
|
break;
|
|
case 1:
|
|
method.invoke(manager, displayId, rotation);
|
|
break;
|
|
default:
|
|
method.invoke(manager, displayId, rotation, "scrcpy#freezeRotation");
|
|
break;
|
|
}
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
}
|
|
}
|
|
|
|
public boolean isRotationFrozen(int displayId) {
|
|
try {
|
|
Method method = getIsDisplayRotationFrozenMethod();
|
|
switch (isDisplayRotationFrozenMethodVersion) {
|
|
case 0:
|
|
if (displayId != 0) {
|
|
Ln.e("Secondary display rotation not supported on this device");
|
|
return false;
|
|
}
|
|
return (boolean) method.invoke(manager);
|
|
default:
|
|
return (boolean) method.invoke(manager, displayId);
|
|
}
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void thawRotation(int displayId) {
|
|
try {
|
|
Method method = getThawDisplayRotationMethod();
|
|
switch (thawDisplayRotationMethodVersion) {
|
|
case 0:
|
|
if (displayId != 0) {
|
|
Ln.e("Secondary display rotation not supported on this device");
|
|
return;
|
|
}
|
|
method.invoke(manager);
|
|
break;
|
|
case 1:
|
|
method.invoke(manager, displayId);
|
|
break;
|
|
default:
|
|
method.invoke(manager, displayId, "scrcpy#thawRotation");
|
|
break;
|
|
}
|
|
} catch (ReflectiveOperationException e) {
|
|
Ln.e("Could not invoke method", e);
|
|
}
|
|
}
|
|
|
|
public void registerRotationWatcher(IRotationWatcher rotationWatcher, int displayId) {
|
|
try {
|
|
Class<?> cls = manager.getClass();
|
|
try {
|
|
// 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, displayId);
|
|
} catch (NoSuchMethodException e) {
|
|
// old version
|
|
cls.getMethod("watchRotation", IRotationWatcher.class).invoke(manager, rotationWatcher);
|
|
}
|
|
} catch (Exception e) {
|
|
Ln.e("Could not register rotation watcher", e);
|
|
}
|
|
}
|
|
|
|
@TargetApi(29)
|
|
public void registerDisplayFoldListener(IDisplayFoldListener foldListener) {
|
|
try {
|
|
Class<?> cls = manager.getClass();
|
|
cls.getMethod("registerDisplayFoldListener", IDisplayFoldListener.class).invoke(manager, foldListener);
|
|
} catch (Exception e) {
|
|
Ln.e("Could not register display fold listener", e);
|
|
}
|
|
}
|
|
}
|