1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1; 4 import static android.os.Build.VERSION_CODES.M; 5 import static android.os.Build.VERSION_CODES.N; 6 import static android.os.Build.VERSION_CODES.Q; 7 import static com.google.common.truth.Truth.assertThat; 8 import static org.mockito.ArgumentMatchers.any; 9 import static org.mockito.ArgumentMatchers.anyInt; 10 import static org.mockito.Mockito.never; 11 import static org.mockito.Mockito.verify; 12 import static org.robolectric.Shadows.shadowOf; 13 14 import android.R; 15 import android.app.Activity; 16 import android.os.Build.VERSION_CODES; 17 import android.os.Bundle; 18 import android.os.Handler; 19 import android.os.Looper; 20 import android.view.FrameMetrics; 21 import android.view.Window; 22 import android.view.WindowManager; 23 import android.widget.LinearLayout; 24 import androidx.test.core.app.ApplicationProvider; 25 import androidx.test.ext.junit.runners.AndroidJUnit4; 26 import org.junit.Test; 27 import org.junit.runner.RunWith; 28 import org.mockito.Mockito; 29 import org.robolectric.Robolectric; 30 import org.robolectric.android.controller.ActivityController; 31 import org.robolectric.annotation.Config; 32 33 @RunWith(AndroidJUnit4.class) 34 public class ShadowWindowTest { 35 @Test getFlag_shouldReturnWindowFlags()36 public void getFlag_shouldReturnWindowFlags() { 37 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 38 Window window = activity.getWindow(); 39 40 assertThat(shadowOf(window).getFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN)).isFalse(); 41 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 42 assertThat(shadowOf(window).getFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN)).isTrue(); 43 window.setFlags(WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON); 44 assertThat(shadowOf(window).getFlag(WindowManager.LayoutParams.FLAG_FULLSCREEN)).isTrue(); 45 } 46 47 @Test getSystemFlag_isFalseByDefault()48 public void getSystemFlag_isFalseByDefault() { 49 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 50 Window window = activity.getWindow(); 51 int fakeSystemFlag1 = 0b1; 52 53 assertThat(shadowOf(window).getPrivateFlag(fakeSystemFlag1)).isFalse(); 54 } 55 56 @Test 57 @Config(minSdk = Q) getSystemFlag_shouldReturnFlagsSetViaAddSystemFlags()58 public void getSystemFlag_shouldReturnFlagsSetViaAddSystemFlags() throws Exception { 59 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 60 Window window = activity.getWindow(); 61 int fakeSystemFlag1 = 0b1; 62 63 window.addSystemFlags(fakeSystemFlag1); 64 65 assertThat(shadowOf(window).getPrivateFlag(fakeSystemFlag1)).isTrue(); 66 } 67 68 @Test 69 @Config(minSdk = Q) getSystemFlag_callingAddSystemFlagsShouldNotOverrideExistingFlags()70 public void getSystemFlag_callingAddSystemFlagsShouldNotOverrideExistingFlags() throws Exception { 71 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 72 Window window = activity.getWindow(); 73 int fakeSystemFlag1 = 0b1; 74 int fakeSystemFlag2 = 0b10; 75 window.addSystemFlags(fakeSystemFlag1); 76 77 window.addSystemFlags(fakeSystemFlag2); 78 79 assertThat(shadowOf(window).getPrivateFlag(fakeSystemFlag1)).isTrue(); 80 } 81 82 @Test 83 @Config(maxSdk = VERSION_CODES.R) getSystemFlag_shouldReturnFlagsSetViaAddPrivateFlags()84 public void getSystemFlag_shouldReturnFlagsSetViaAddPrivateFlags() throws Exception { 85 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 86 Window window = activity.getWindow(); 87 int fakeSystemFlag1 = 0b1; 88 89 window.addPrivateFlags(fakeSystemFlag1); 90 91 assertThat(shadowOf(window).getPrivateFlag(fakeSystemFlag1)).isTrue(); 92 } 93 94 @Test 95 @Config(maxSdk = VERSION_CODES.R) getSystemFlag_callingAddPrivateFlagsShouldNotOverrideExistingFlags()96 public void getSystemFlag_callingAddPrivateFlagsShouldNotOverrideExistingFlags() 97 throws Exception { 98 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 99 Window window = activity.getWindow(); 100 int fakeSystemFlag1 = 0b1; 101 int fakeSystemFlag2 = 0b10; 102 window.addPrivateFlags(fakeSystemFlag1); 103 104 window.addPrivateFlags(fakeSystemFlag2); 105 106 assertThat(shadowOf(window).getPrivateFlag(fakeSystemFlag1)).isTrue(); 107 } 108 109 @Test getTitle_shouldReturnWindowTitle()110 public void getTitle_shouldReturnWindowTitle() { 111 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 112 Window window = activity.getWindow(); 113 window.setTitle("My Window Title"); 114 assertThat(shadowOf(window).getTitle().toString()).isEqualTo("My Window Title"); 115 } 116 117 @Test getBackgroundDrawable_returnsSetDrawable()118 public void getBackgroundDrawable_returnsSetDrawable() { 119 Activity activity = Robolectric.buildActivity(Activity.class).create().get(); 120 Window window = activity.getWindow(); 121 ShadowWindow shadowWindow = shadowOf(window); 122 123 assertThat(shadowWindow.getBackgroundDrawable()).isNull(); 124 125 window.setBackgroundDrawableResource(R.drawable.btn_star); 126 assertThat(shadowOf(shadowWindow.getBackgroundDrawable()).createdFromResId).isEqualTo(R.drawable.btn_star); 127 } 128 129 @Test getSoftInputMode_returnsSoftInputMode()130 public void getSoftInputMode_returnsSoftInputMode() { 131 TestActivity activity = Robolectric.buildActivity(TestActivity.class).create().get(); 132 Window window = activity.getWindow(); 133 ShadowWindow shadowWindow = shadowOf(window); 134 135 window.setSoftInputMode(7); 136 137 assertThat(shadowWindow.getSoftInputMode()).isEqualTo(7); 138 } 139 140 @Test @Config(maxSdk = LOLLIPOP_MR1) forPreM_create_shouldCreateImplPhoneWindow()141 public void forPreM_create_shouldCreateImplPhoneWindow() throws Exception { 142 assertThat( 143 ShadowWindow.create(ApplicationProvider.getApplicationContext()).getClass().getName()) 144 .isEqualTo("com.android.internal.policy.impl.PhoneWindow"); 145 } 146 147 @Test @Config(minSdk = M) forM_create_shouldCreatePhoneWindow()148 public void forM_create_shouldCreatePhoneWindow() throws Exception { 149 assertThat( 150 ShadowWindow.create(ApplicationProvider.getApplicationContext()).getClass().getName()) 151 .isEqualTo("com.android.internal.policy.PhoneWindow"); 152 } 153 154 @Test 155 @Config(minSdk = N) reportOnFrameMetricsAvailable_notifiesListeners()156 public void reportOnFrameMetricsAvailable_notifiesListeners() throws Exception { 157 ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class); 158 159 // Attaches the ViewRootImpl to the window. 160 // When the ViewRootImpl is attached, android will check to see if hardware acceleration is 161 // enabled, and only attach listeners if it is. Attaching, rather than just using a created 162 // window, allows for verification that triggering works even then. 163 activityController.setup(); 164 165 Window window = activityController.get().getWindow(); 166 Window.OnFrameMetricsAvailableListener listener = 167 Mockito.mock(Window.OnFrameMetricsAvailableListener.class); 168 FrameMetrics frameMetrics = new FrameMetricsBuilder().build(); 169 170 window.addOnFrameMetricsAvailableListener(listener, new Handler(Looper.getMainLooper())); 171 shadowOf(window).reportOnFrameMetricsAvailable(frameMetrics); 172 173 verify(listener) 174 .onFrameMetricsAvailable(window, frameMetrics, /* dropCountSinceLastInvocation= */ 0); 175 } 176 177 @Test 178 @Config(minSdk = N) reportOnFrameMetricsAvailable_nonZeroDropCount_notifiesListeners()179 public void reportOnFrameMetricsAvailable_nonZeroDropCount_notifiesListeners() throws Exception { 180 ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class); 181 activityController.setup(); 182 183 Window window = activityController.get().getWindow(); 184 Window.OnFrameMetricsAvailableListener listener = 185 Mockito.mock(Window.OnFrameMetricsAvailableListener.class); 186 FrameMetrics frameMetrics = new FrameMetricsBuilder().build(); 187 188 window.addOnFrameMetricsAvailableListener(listener, new Handler(Looper.getMainLooper())); 189 shadowOf(window) 190 .reportOnFrameMetricsAvailable(frameMetrics, /* dropCountSinceLastInvocation= */ 3); 191 192 verify(listener) 193 .onFrameMetricsAvailable(window, frameMetrics, /* dropCountSinceLastInvocation= */ 3); 194 } 195 196 @Test 197 @Config(minSdk = N) reportOnFrameMetricsAvailable_listenerRemoved_doesntNotifyListener()198 public void reportOnFrameMetricsAvailable_listenerRemoved_doesntNotifyListener() 199 throws Exception { 200 ActivityController<Activity> activityController = Robolectric.buildActivity(Activity.class); 201 activityController.setup(); 202 203 Window window = activityController.get().getWindow(); 204 Window.OnFrameMetricsAvailableListener listener = 205 Mockito.mock(Window.OnFrameMetricsAvailableListener.class); 206 FrameMetrics frameMetrics = new FrameMetricsBuilder().build(); 207 208 window.addOnFrameMetricsAvailableListener(listener, new Handler(Looper.getMainLooper())); 209 window.removeOnFrameMetricsAvailableListener(listener); 210 shadowOf(window).reportOnFrameMetricsAvailable(frameMetrics); 211 212 verify(listener, never()) 213 .onFrameMetricsAvailable( 214 any(Window.class), 215 any(FrameMetrics.class), 216 /* dropCountSinceLastInvocation= */ anyInt()); 217 } 218 219 @Test 220 @Config(minSdk = N) reportOnFrameMetricsAvailable_noListener_doesntCrash()221 public void reportOnFrameMetricsAvailable_noListener_doesntCrash() throws Exception { 222 Window window = ShadowWindow.create(ApplicationProvider.getApplicationContext()); 223 224 // Shouldn't crash. 225 shadowOf(window).reportOnFrameMetricsAvailable(new FrameMetricsBuilder().build()); 226 } 227 228 public static class TestActivity extends Activity { 229 public int requestFeature = Window.FEATURE_PROGRESS; 230 231 @Override onCreate(Bundle savedInstanceState)232 protected void onCreate(Bundle savedInstanceState) { 233 super.onCreate(savedInstanceState); 234 setTheme(R.style.Theme_Holo_Light); 235 getWindow().requestFeature(requestFeature); 236 setContentView(new LinearLayout(this)); 237 getActionBar().setIcon(R.drawable.ic_lock_power_off); 238 } 239 } 240 } 241