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 freezeRotationMethod; private Method freezeDisplayRotationMethod; private Method isRotationFrozenMethod; private Method isDisplayRotationFrozenMethod; private Method thawRotationMethod; private Method thawDisplayRotationMethod; 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 getFreezeRotationMethod() throws NoSuchMethodException { if (freezeRotationMethod == null) { freezeRotationMethod = manager.getClass().getMethod("freezeRotation", int.class); } return freezeRotationMethod; } // New method added by this commit: // private Method getFreezeDisplayRotationMethod() throws NoSuchMethodException { if (freezeDisplayRotationMethod == null) { freezeDisplayRotationMethod = manager.getClass().getMethod("freezeDisplayRotation", int.class, int.class); } return freezeDisplayRotationMethod; } private Method getIsRotationFrozenMethod() throws NoSuchMethodException { if (isRotationFrozenMethod == null) { isRotationFrozenMethod = manager.getClass().getMethod("isRotationFrozen"); } return isRotationFrozenMethod; } // New method added by this commit: // private Method getIsDisplayRotationFrozenMethod() throws NoSuchMethodException { if (isDisplayRotationFrozenMethod == null) { isDisplayRotationFrozenMethod = manager.getClass().getMethod("isDisplayRotationFrozen", int.class); } return isDisplayRotationFrozenMethod; } private Method getThawRotationMethod() throws NoSuchMethodException { if (thawRotationMethod == null) { thawRotationMethod = manager.getClass().getMethod("thawRotation"); } return thawRotationMethod; } // New method added by this commit: // private Method getThawDisplayRotationMethod() throws NoSuchMethodException { if (thawDisplayRotationMethod == null) { thawDisplayRotationMethod = manager.getClass().getMethod("thawDisplayRotation", int.class); } 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 { try { Method method = getFreezeDisplayRotationMethod(); method.invoke(manager, displayId, rotation); } catch (ReflectiveOperationException e) { if (displayId == 0) { Method method = getFreezeRotationMethod(); method.invoke(manager, rotation); } else { Ln.e("Could not invoke method", e); } } } catch (ReflectiveOperationException e) { Ln.e("Could not invoke method", e); } } public boolean isRotationFrozen(int displayId) { try { try { Method method = getIsDisplayRotationFrozenMethod(); return (boolean) method.invoke(manager, displayId); } catch (ReflectiveOperationException e) { if (displayId == 0) { Method method = getIsRotationFrozenMethod(); return (boolean) method.invoke(manager); } else { Ln.e("Could not invoke method", e); return false; } } } catch (ReflectiveOperationException e) { Ln.e("Could not invoke method", e); return false; } } public void thawRotation(int displayId) { try { try { Method method = getThawDisplayRotationMethod(); method.invoke(manager, displayId); } catch (ReflectiveOperationException e) { if (displayId == 0) { Method method = getThawRotationMethod(); method.invoke(manager); } else { Ln.e("Could not invoke method", e); } } } 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); } } }