diff options
Diffstat (limited to 'shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java')
-rw-r--r-- | shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java | 292 |
1 files changed, 48 insertions, 244 deletions
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java index 80b484cdc..75b0371eb 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowWindowManagerGlobal.java @@ -2,40 +2,25 @@ package org.robolectric.shadows; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; -import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; -import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.P; -import static android.os.Build.VERSION_CODES.Q; import static android.os.Build.VERSION_CODES.R; -import static android.os.Build.VERSION_CODES.S; -import static android.os.Build.VERSION_CODES.S_V2; import static org.robolectric.shadows.ShadowView.useRealGraphics; import static org.robolectric.util.reflector.Reflector.reflector; import android.app.Instrumentation; import android.content.ClipData; import android.content.Context; -import android.graphics.Rect; import android.os.Binder; -import android.os.Build.VERSION; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; -import android.view.DisplayCutout; -import android.view.IWindow; import android.view.IWindowManager; import android.view.IWindowSession; -import android.view.InputChannel; -import android.view.InsetsSourceControl; -import android.view.InsetsState; -import android.view.InsetsVisibilities; -import android.view.Surface; -import android.view.SurfaceControl; import android.view.View; -import android.view.WindowManager; import android.view.WindowManagerGlobal; import androidx.annotation.Nullable; +import java.lang.reflect.Proxy; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; @@ -53,44 +38,18 @@ import org.robolectric.util.reflector.Static; minSdk = JELLY_BEAN_MR1, looseSignatures = true) public class ShadowWindowManagerGlobal { - private static WindowSessionDelegate windowSessionDelegate; + private static WindowSessionDelegate windowSessionDelegate = new WindowSessionDelegate(); private static IWindowSession windowSession; @Resetter public static void reset() { reflector(WindowManagerGlobalReflector.class).setDefaultWindowManager(null); - windowSessionDelegate = null; + windowSessionDelegate = new WindowSessionDelegate(); windowSession = null; } - private static synchronized WindowSessionDelegate getWindowSessionDelegate() { - if (windowSessionDelegate == null) { - int apiLevel = RuntimeEnvironment.getApiLevel(); - if (apiLevel >= S_V2) { - windowSessionDelegate = new WindowSessionDelegateSV2(); - } else if (apiLevel >= S) { - windowSessionDelegate = new WindowSessionDelegateS(); - } else if (apiLevel >= R) { - windowSessionDelegate = new WindowSessionDelegateR(); - } else if (apiLevel >= Q) { - windowSessionDelegate = new WindowSessionDelegateQ(); - } else if (apiLevel >= P) { - windowSessionDelegate = new WindowSessionDelegateP(); - } else if (apiLevel >= M) { - windowSessionDelegate = new WindowSessionDelegateM(); - } else if (apiLevel >= LOLLIPOP_MR1) { - windowSessionDelegate = new WindowSessionDelegateLMR1(); - } else if (apiLevel >= JELLY_BEAN_MR1) { - windowSessionDelegate = new WindowSessionDelegateJBMR1(); - } else { - windowSessionDelegate = new WindowSessionDelegateJB(); - } - } - return windowSessionDelegate; - } - public static boolean getInTouchMode() { - return getWindowSessionDelegate().getInTouchMode(); + return windowSessionDelegate.getInTouchMode(); } /** @@ -98,7 +57,7 @@ public class ShadowWindowManagerGlobal { * Instrumentation#setInTouchMode(boolean)} to modify this from a test. */ static void setInTouchMode(boolean inTouchMode) { - getWindowSessionDelegate().setInTouchMode(inTouchMode); + windowSessionDelegate.setInTouchMode(inTouchMode); } /** @@ -107,21 +66,46 @@ public class ShadowWindowManagerGlobal { */ @Nullable public static ClipData getLastDragClipData() { - return windowSessionDelegate != null ? windowSessionDelegate.lastDragClipData : null; + return windowSessionDelegate.lastDragClipData; } /** Clears the data returned by {@link #getLastDragClipData()}. */ public static void clearLastDragClipData() { - if (windowSessionDelegate != null) { - windowSessionDelegate.lastDragClipData = null; - } + windowSessionDelegate.lastDragClipData = null; } @Implementation(minSdk = JELLY_BEAN_MR2) protected static synchronized IWindowSession getWindowSession() { if (windowSession == null) { + // Use Proxy.newProxyInstance instead of ReflectionHelpers.createDelegatingProxy as there are + // too many variants of 'add', 'addToDisplay', and 'addToDisplayAsUser', some of which have + // arg types that don't exist any more. windowSession = - ReflectionHelpers.createDelegatingProxy(IWindowSession.class, getWindowSessionDelegate()); + (IWindowSession) + Proxy.newProxyInstance( + IWindowSession.class.getClassLoader(), + new Class<?>[] {IWindowSession.class}, + (proxy, method, args) -> { + String methodName = method.getName(); + switch (methodName) { + case "add": // SDK 16 + case "addToDisplay": // SDK 17-29 + case "addToDisplayAsUser": // SDK 30+ + return windowSessionDelegate.getAddFlags(); + case "getInTouchMode": + return windowSessionDelegate.getInTouchMode(); + case "performDrag": + return windowSessionDelegate.performDrag(args); + case "prepareDrag": + return windowSessionDelegate.prepareDrag(); + case "setInTouchMode": + windowSessionDelegate.setInTouchMode((boolean) args[0]); + return null; + default: + return ReflectionHelpers.defaultValueForType( + method.getReturnType().getName()); + } + }); } return windowSession; } @@ -143,7 +127,7 @@ public class ShadowWindowManagerGlobal { if (service == null) { service = IWindowManager.Stub.asInterface(ServiceManager.getService(Context.WINDOW_SERVICE)); reflector(WindowManagerGlobalReflector.class).setWindowManagerService(service); - if (VERSION.SDK_INT >= 30) { + if (RuntimeEnvironment.getApiLevel() >= R) { reflector(WindowManagerGlobalReflector.class).setUseBlastAdapter(service.useBLAST()); } } @@ -169,7 +153,7 @@ public class ShadowWindowManagerGlobal { void setUseBlastAdapter(boolean useBlastAdapter); } - private abstract static class WindowSessionDelegate { + private static class WindowSessionDelegate { // From WindowManagerGlobal (was WindowManagerImpl in JB). static final int ADD_FLAG_IN_TOUCH_MODE = 0x1; static final int ADD_FLAG_APP_VISIBLE = 0x2; @@ -202,200 +186,20 @@ public class ShadowWindowManagerGlobal { this.inTouchMode = inTouchMode; } - // @Implementation(maxSdk = O_MR1) - public IBinder prepareDrag( - IWindow window, int flags, int thumbnailWidth, int thumbnailHeight, Surface outSurface) { - return new Binder(); - } - - // @Implementation(maxSdk = M) - public boolean performDrag( - IWindow window, - IBinder dragToken, - float touchX, - float touchY, - float thumbCenterX, - float thumbCenterY, - ClipData data) { - lastDragClipData = data; - return true; - } - - // @Implementation(minSdk = N, maxSdk = O_MR1) - public boolean performDrag( - IWindow window, - IBinder dragToken, - int touchSource, - float touchX, - float touchY, - float thumbCenterX, - float thumbCenterY, - ClipData data) { - lastDragClipData = data; - return true; - } - } - - private static class WindowSessionDelegateJB extends WindowSessionDelegate { - // @Implementation(maxSdk = JELLY_BEAN) - public int add( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outContentInsets, - InputChannel outInputChannel) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateJBMR1 extends WindowSessionDelegateJB { - // @Implementation(minSdk = JELLY_BEAN_MR1, maxSdk = LOLLIPOP) - public int addToDisplay( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outContentInsets, - InputChannel outInputChannel) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateLMR1 extends WindowSessionDelegateJBMR1 { - // @Implementation(sdk = LOLLIPOP_MR1) - public int addToDisplay( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outContentInsets, - Rect outStableInsets, - InputChannel outInputChannel) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateM extends WindowSessionDelegateLMR1 { - // @Implementation(minSdk = M, maxSdk = O_MR1) - public int addToDisplay( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outContentInsets, - Rect outStableInsets, - Rect outInsets, - InputChannel outInputChannel) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateP extends WindowSessionDelegateM { - // @Implementation(sdk = P) - public int addToDisplay( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outFrame, - Rect outContentInsets, - Rect outStableInsets, - Rect outOutsets, - DisplayCutout.ParcelableWrapper displayCutout, - InputChannel outInputChannel) { - return getAddFlags(); - } - - // @Implementation(minSdk = P) - public IBinder performDrag( - IWindow window, - int flags, - SurfaceControl surface, - int touchSource, - float touchX, - float touchY, - float thumbCenterX, - float thumbCenterY, - ClipData data) { - lastDragClipData = data; + public IBinder prepareDrag() { return new Binder(); } - } - private static class WindowSessionDelegateQ extends WindowSessionDelegateP { - // @Implementation(sdk = Q) - public int addToDisplay( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - Rect outFrame, - Rect outContentInsets, - Rect outStableInsets, - Rect outOutsets, - DisplayCutout.ParcelableWrapper displayCutout, - InputChannel outInputChannel, - InsetsState insetsState) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateR extends WindowSessionDelegateQ { - // @Implementation(sdk = R) - public int addToDisplayAsUser( - IWindow window, - int seq, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - int userId, - Rect outFrame, - Rect outContentInsets, - Rect outStableInsets, - DisplayCutout.ParcelableWrapper displayCutout, - InputChannel outInputChannel, - InsetsState insetsState, - InsetsSourceControl[] activeControls) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateS extends WindowSessionDelegateR { - // @Implementation(sdk = S) - public int addToDisplayAsUser( - IWindow window, - WindowManager.LayoutParams attrs, - int viewVisibility, - int layerStackId, - int userId, - InsetsState requestedVisibility, - InputChannel outInputChannel, - InsetsState insetsState, - InsetsSourceControl[] activeControls) { - return getAddFlags(); - } - } - - private static class WindowSessionDelegateSV2 extends WindowSessionDelegateS { - // @Implementation(minSdk = S_V2) - public int addToDisplayAsUser( - IWindow window, - WindowManager.LayoutParams attrs, - int viewVisibility, - int displayId, - int userId, - InsetsVisibilities requestedVisibilities, - InputChannel outInputChannel, - InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls) { - return getAddFlags(); + public Object performDrag(Object[] args) { + // extract the clipData param + for (int i = args.length - 1; i >= 0; i--) { + if (args[i] instanceof ClipData) { + lastDragClipData = (ClipData) args[i]; + // In P (SDK 28), the return type changed from boolean to Binder. + return RuntimeEnvironment.getApiLevel() >= P ? new Binder() : true; + } + } + throw new AssertionError("Missing ClipData param"); } } } |