1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.JELLY_BEAN; 4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 5 6 import android.content.Context; 7 import android.content.res.Configuration; 8 import android.graphics.Rect; 9 import android.os.Build; 10 import android.os.Looper; 11 import android.util.MergedConfiguration; 12 import android.view.Display; 13 import android.view.IWindowSession; 14 import android.view.ViewRootImpl; 15 import android.view.WindowManager; 16 import java.util.ArrayList; 17 import org.robolectric.RuntimeEnvironment; 18 import org.robolectric.annotation.Implementation; 19 import org.robolectric.annotation.Implements; 20 import org.robolectric.annotation.RealObject; 21 import org.robolectric.annotation.Resetter; 22 import org.robolectric.util.ReflectionHelpers; 23 import org.robolectric.util.ReflectionHelpers.ClassParameter; 24 25 @Implements(value = ViewRootImpl.class, isInAndroidSdk = false) 26 public class ShadowViewRootImpl { 27 28 @RealObject private ViewRootImpl realObject; 29 30 @Implementation(maxSdk = JELLY_BEAN) 31 public static IWindowSession getWindowSession(Looper mainLooper) { 32 return null; 33 } 34 35 @Implementation 36 public void playSoundEffect(int effectId) { 37 } 38 39 public void callDispatchResized() { 40 Display display = getDisplay(); 41 Rect frame = new Rect(); 42 display.getRectSize(frame); 43 Rect zeroSizedRect = new Rect(0, 0, 0, 0); 44 45 int apiLevel = RuntimeEnvironment.getApiLevel(); 46 ViewRootImpl component = realObject; 47 if (apiLevel <= Build.VERSION_CODES.JELLY_BEAN) { 48 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 49 ClassParameter.from(int.class, frame.width()), 50 ClassParameter.from(int.class, frame.height()), 51 ClassParameter.from(Rect.class, zeroSizedRect), 52 ClassParameter.from(Rect.class, zeroSizedRect), 53 ClassParameter.from(boolean.class, true), 54 ClassParameter.from(Configuration.class, null)); 55 } else if (apiLevel <= JELLY_BEAN_MR1) { 56 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 57 ClassParameter.from(Rect.class, frame), 58 ClassParameter.from(Rect.class, zeroSizedRect), 59 ClassParameter.from(Rect.class, zeroSizedRect), 60 ClassParameter.from(boolean.class, true), 61 ClassParameter.from(Configuration.class, null)); 62 } else if (apiLevel <= Build.VERSION_CODES.KITKAT) { 63 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 64 ClassParameter.from(Rect.class, frame), 65 ClassParameter.from(Rect.class, zeroSizedRect), 66 ClassParameter.from(Rect.class, zeroSizedRect), 67 ClassParameter.from(Rect.class, zeroSizedRect), 68 ClassParameter.from(boolean.class, true), 69 ClassParameter.from(Configuration.class, null)); 70 } else if (apiLevel <= Build.VERSION_CODES.LOLLIPOP_MR1) { 71 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 72 ClassParameter.from(Rect.class, frame), 73 ClassParameter.from(Rect.class, zeroSizedRect), 74 ClassParameter.from(Rect.class, zeroSizedRect), 75 ClassParameter.from(Rect.class, zeroSizedRect), 76 ClassParameter.from(Rect.class, zeroSizedRect), 77 ClassParameter.from(boolean.class, true), 78 ClassParameter.from(Configuration.class, null)); 79 } else if (apiLevel <= Build.VERSION_CODES.M) { 80 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 81 ClassParameter.from(Rect.class, frame), 82 ClassParameter.from(Rect.class, zeroSizedRect), 83 ClassParameter.from(Rect.class, zeroSizedRect), 84 ClassParameter.from(Rect.class, zeroSizedRect), 85 ClassParameter.from(Rect.class, zeroSizedRect), 86 ClassParameter.from(Rect.class, zeroSizedRect), 87 ClassParameter.from(boolean.class, true), 88 ClassParameter.from(Configuration.class, null)); 89 } else if (apiLevel <= Build.VERSION_CODES.N_MR1) { 90 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 91 ClassParameter.from(Rect.class, frame), 92 ClassParameter.from(Rect.class, zeroSizedRect), 93 ClassParameter.from(Rect.class, zeroSizedRect), 94 ClassParameter.from(Rect.class, zeroSizedRect), 95 ClassParameter.from(Rect.class, zeroSizedRect), 96 ClassParameter.from(Rect.class, zeroSizedRect), 97 ClassParameter.from(boolean.class, true), 98 ClassParameter.from(Configuration.class, null), 99 ClassParameter.from(Rect.class, frame), 100 ClassParameter.from(boolean.class, false), 101 ClassParameter.from(boolean.class, false)); 102 } else if (apiLevel <= Build.VERSION_CODES.O_MR1) { 103 ReflectionHelpers.callInstanceMethod( 104 ViewRootImpl.class, 105 component, 106 "dispatchResized", 107 ClassParameter.from(Rect.class, frame), 108 ClassParameter.from(Rect.class, zeroSizedRect), 109 ClassParameter.from(Rect.class, zeroSizedRect), 110 ClassParameter.from(Rect.class, zeroSizedRect), 111 ClassParameter.from(Rect.class, zeroSizedRect), 112 ClassParameter.from(Rect.class, zeroSizedRect), 113 ClassParameter.from(boolean.class, true), 114 ClassParameter.from(MergedConfiguration.class, new MergedConfiguration()), 115 ClassParameter.from(Rect.class, frame), 116 ClassParameter.from(boolean.class, false), 117 ClassParameter.from(boolean.class, false), 118 ClassParameter.from(int.class, 0)); 119 120 } else if (apiLevel >= Build.VERSION_CODES.P) { 121 ReflectionHelpers.callInstanceMethod(ViewRootImpl.class, component, "dispatchResized", 122 ClassParameter.from(Rect.class, frame), 123 ClassParameter.from(Rect.class, zeroSizedRect), 124 ClassParameter.from(Rect.class, zeroSizedRect), 125 ClassParameter.from(Rect.class, zeroSizedRect), 126 ClassParameter.from(Rect.class, zeroSizedRect), 127 ClassParameter.from(Rect.class, zeroSizedRect), 128 ClassParameter.from(boolean.class, true), 129 ClassParameter.from(MergedConfiguration.class, new MergedConfiguration()), 130 ClassParameter.from(Rect.class, frame), 131 ClassParameter.from(boolean.class, false), 132 ClassParameter.from(boolean.class, false), 133 ClassParameter.from(int.class, 0), 134 ClassParameter.from(android.view.DisplayCutout.ParcelableWrapper.class, 135 new android.view.DisplayCutout.ParcelableWrapper())); 136 137 } else { 138 throw new RuntimeException("Could not find AndroidRuntimeAdapter for API level: " + apiLevel); 139 } 140 } 141 142 private Display getDisplay() { 143 if (RuntimeEnvironment.getApiLevel() > JELLY_BEAN_MR1) { 144 return realObject.getView().getDisplay(); 145 } else { 146 WindowManager windowManager = (WindowManager) realObject.getView().getContext() 147 .getSystemService(Context.WINDOW_SERVICE); 148 return windowManager.getDefaultDisplay(); 149 } 150 } 151 152 @Resetter 153 public static void reset() { 154 ReflectionHelpers.setStaticField(ViewRootImpl.class, "sRunQueues", new ThreadLocal<>()); 155 ReflectionHelpers.setStaticField(ViewRootImpl.class, "sFirstDrawHandlers", new ArrayList<>()); 156 ReflectionHelpers.setStaticField(ViewRootImpl.class, "sFirstDrawComplete", false); 157 ReflectionHelpers.setStaticField(ViewRootImpl.class, "sConfigCallbacks", new ArrayList<>()); 158 } 159 } 160