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 import static org.assertj.core.api.Assertions.assertThat; 6 import static org.assertj.core.api.Assertions.assertThatThrownBy; 7 import static org.robolectric.shadows.ShadowDisplayManagerTest.HideFromJB.getGlobal; 8 9 import android.content.Context; 10 import android.graphics.Point; 11 import android.hardware.display.DisplayManager; 12 import android.hardware.display.DisplayManagerGlobal; 13 import android.view.Display; 14 import android.view.DisplayInfo; 15 import android.view.Surface; 16 import java.util.ArrayList; 17 import java.util.List; 18 import org.junit.Before; 19 import org.junit.Test; 20 import org.junit.runner.RunWith; 21 import org.robolectric.RobolectricTestRunner; 22 import org.robolectric.RuntimeEnvironment; 23 import org.robolectric.annotation.Config; 24 import org.robolectric.shadow.api.Shadow; 25 26 @RunWith(RobolectricTestRunner.class) 27 public class ShadowDisplayManagerTest { 28 29 private DisplayManager instance; 30 31 @Before 32 public void setUp() throws Exception { 33 instance = (DisplayManager) RuntimeEnvironment.application 34 .getSystemService(Context.DISPLAY_SERVICE); 35 } 36 37 @Test @Config(maxSdk = JELLY_BEAN) 38 public void notSupportedInJellyBean() throws Exception { 39 assertThatThrownBy(() -> ShadowDisplayManager.removeDisplay(0)) 40 .isInstanceOf(UnsupportedOperationException.class) 41 .hasMessageContaining("displays not supported in Jelly Bean"); 42 } 43 44 @Test 45 @Config(minSdk = JELLY_BEAN_MR1) 46 public void getDisplayInfo_shouldReturnCopy() throws Exception { 47 DisplayInfo displayInfo = getGlobal().getDisplayInfo(Display.DEFAULT_DISPLAY); 48 int origAppWidth = displayInfo.appWidth; 49 displayInfo.appWidth++; 50 assertThat(getGlobal().getDisplayInfo(Display.DEFAULT_DISPLAY).appWidth) 51 .isEqualTo(origAppWidth); 52 } 53 54 @Test 55 @Config(minSdk = JELLY_BEAN_MR1) 56 public void forNonexistentDisplay_getDisplayInfo_shouldReturnNull() throws Exception { 57 assertThat(getGlobal().getDisplayInfo(3)).isEqualTo(null); 58 } 59 60 @Test 61 @Config(minSdk = JELLY_BEAN_MR1) 62 public void forNonexistentDisplay_changeDisplay_shouldThrow() throws Exception { 63 assertThatThrownBy(() -> ShadowDisplayManager.changeDisplay(3, "")) 64 .hasMessageContaining("no display 3"); 65 } 66 67 @Test 68 @Config(minSdk = JELLY_BEAN_MR1) 69 public void forNonexistentDisplay_removeDisplay_shouldThrow() throws Exception { 70 assertThatThrownBy(() -> ShadowDisplayManager.removeDisplay(3)) 71 .hasMessageContaining("no display 3"); 72 } 73 74 @Test @Config(minSdk = JELLY_BEAN_MR1) 75 public void addDisplay() throws Exception { 76 int displayId = ShadowDisplayManager.addDisplay("w100dp-h200dp"); 77 assertThat(displayId).isGreaterThan(0); 78 79 DisplayInfo di = getGlobal().getDisplayInfo(displayId); 80 assertThat(di.appWidth).isEqualTo(100); 81 assertThat(di.appHeight).isEqualTo(200); 82 83 Display display = instance.getDisplay(displayId); 84 assertThat(display.getDisplayId()).isEqualTo(displayId); 85 } 86 87 @Test @Config(minSdk = JELLY_BEAN_MR1) 88 public void addDisplay_shouldNotifyListeners() throws Exception { 89 List<String> events = new ArrayList<>(); 90 instance.registerDisplayListener(new MyDisplayListener(events), null); 91 int displayId = ShadowDisplayManager.addDisplay("w100dp-h200dp"); 92 assertThat(events).containsExactly("Added " + displayId); 93 } 94 95 @Test @Config(minSdk = JELLY_BEAN_MR1) 96 public void changeDisplay_shouldUpdateSmallestAndLargestNominalWidthAndHeight() throws Exception { 97 Point smallest = new Point(); 98 Point largest = new Point(); 99 100 ShadowDisplay.getDefaultDisplay().getCurrentSizeRange(smallest, largest); 101 assertThat(smallest).isEqualTo(new Point(320, 320)); 102 assertThat(largest).isEqualTo(new Point(470, 470)); 103 104 Display display = ShadowDisplay.getDefaultDisplay(); 105 ShadowDisplay shadowDisplay = Shadow.extract(display); 106 shadowDisplay.setWidth(display.getWidth() - 10); 107 shadowDisplay.setHeight(display.getHeight() - 10); 108 109 ShadowDisplay.getDefaultDisplay().getCurrentSizeRange(smallest, largest); 110 assertThat(smallest).isEqualTo(new Point(310, 310)); 111 assertThat(largest).isEqualTo(new Point(460, 460)); 112 } 113 114 @Test @Config(minSdk = JELLY_BEAN_MR1) 115 public void withQualifiers_changeDisplay_shouldUpdateSmallestAndLargestNominalWidthAndHeight() throws Exception { 116 Point smallest = new Point(); 117 Point largest = new Point(); 118 119 Display display = ShadowDisplay.getDefaultDisplay(); 120 display.getCurrentSizeRange(smallest, largest); 121 assertThat(smallest).isEqualTo(new Point(320, 320)); 122 assertThat(largest).isEqualTo(new Point(470, 470)); 123 124 ShadowDisplayManager.changeDisplay(display.getDisplayId(), "w310dp-h460dp"); 125 126 display.getCurrentSizeRange(smallest, largest); 127 assertThat(smallest).isEqualTo(new Point(310, 310)); 128 assertThat(largest).isEqualTo(new Point(460, 460)); 129 } 130 131 @Test @Config(minSdk = JELLY_BEAN_MR1) 132 public void changeAndRemoveDisplay_shouldNotifyListeners() throws Exception { 133 List<String> events = new ArrayList<>(); 134 instance.registerDisplayListener(new MyDisplayListener(events), null); 135 int displayId = ShadowDisplayManager.addDisplay("w100dp-h200dp"); 136 137 ShadowDisplayManager.changeDisplay(displayId, "w300dp-h400dp"); 138 139 Display display = getGlobal().getRealDisplay(displayId); 140 assertThat(display.getWidth()).isEqualTo(300); 141 assertThat(display.getHeight()).isEqualTo(400); 142 assertThat(display.getOrientation()).isEqualTo(Surface.ROTATION_0); 143 144 ShadowDisplayManager.removeDisplay(displayId); 145 146 assertThat(events).containsExactly( 147 "Added " + displayId, 148 "Changed " + displayId, 149 "Removed " + displayId); 150 } 151 152 @Test @Config(minSdk = JELLY_BEAN_MR1) 153 public void changeDisplay_shouldAllowPartialChanges() throws Exception { 154 List<String> events = new ArrayList<>(); 155 instance.registerDisplayListener(new MyDisplayListener(events), null); 156 int displayId = ShadowDisplayManager.addDisplay("w100dp-h200dp"); 157 158 ShadowDisplayManager.changeDisplay(displayId, "+h201dp-land"); 159 160 Display display = getGlobal().getRealDisplay(displayId); 161 assertThat(display.getWidth()).isEqualTo(201); 162 assertThat(display.getHeight()).isEqualTo(100); 163 assertThat(display.getOrientation()).isEqualTo(Surface.ROTATION_90); 164 165 assertThat(events).containsExactly( 166 "Added " + displayId, 167 "Changed " + displayId); 168 } 169 170 // because DisplayInfo and DisplayManagerGlobal don't exist in Jelly Bean, 171 // and we don't want them resolved as part of the test class. 172 static class HideFromJB { 173 static DisplayInfo createDisplayInfo(int width, int height) { 174 DisplayInfo displayInfo = new DisplayInfo(); 175 displayInfo.appWidth = width; 176 displayInfo.appHeight = height; 177 return displayInfo; 178 } 179 180 public static DisplayManagerGlobal getGlobal() { 181 return DisplayManagerGlobal.getInstance(); 182 } 183 } 184 185 private static class MyDisplayListener implements DisplayManager.DisplayListener { 186 private final List<String> events; 187 188 MyDisplayListener(List<String> events) { 189 this.events = events; 190 } 191 192 @Override 193 public void onDisplayAdded(int displayId) { 194 events.add("Added " + displayId); 195 } 196 197 @Override 198 public void onDisplayRemoved(int displayId) { 199 events.add("Removed " + displayId); 200 } 201 202 @Override 203 public void onDisplayChanged(int displayId) { 204 events.add("Changed " + displayId); 205 } 206 } 207 } 208