1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.setupwizardlib.test; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertEquals; 22 23 import android.annotation.SuppressLint; 24 import android.app.Dialog; 25 import android.content.Context; 26 import android.os.Build.VERSION; 27 import android.os.Build.VERSION_CODES; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.SystemClock; 31 import android.support.test.InstrumentationRegistry; 32 import android.support.test.annotation.UiThreadTest; 33 import android.support.test.filters.SmallTest; 34 import android.support.test.rule.UiThreadTestRule; 35 import android.support.test.runner.AndroidJUnit4; 36 import android.view.ContextThemeWrapper; 37 import android.view.View; 38 import android.view.Window; 39 import android.view.WindowManager; 40 41 import com.android.setupwizardlib.test.util.MockWindow; 42 import com.android.setupwizardlib.util.SystemBarHelper; 43 44 import org.junit.Rule; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 48 @RunWith(AndroidJUnit4.class) 49 @SmallTest 50 public class SystemBarHelperTest { 51 52 @Rule 53 public UiThreadTestRule mUiThreadTestRule = new UiThreadTestRule(); 54 55 private static final int STATUS_BAR_DISABLE_BACK = 0x00400000; 56 57 @SuppressLint("InlinedApi") 58 private static final int DEFAULT_IMMERSIVE_FLAGS = 59 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 60 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 61 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 62 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 63 64 @SuppressLint("InlinedApi") 65 private static final int DIALOG_IMMERSIVE_FLAGS = 66 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 67 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 68 69 @UiThreadTest 70 @Test 71 public void testAddVisibilityFlagView() { 72 final View view = createViewWithSystemUiVisibility(0x456); 73 SystemBarHelper.addVisibilityFlag(view, 0x1400); 74 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 75 // Check that result is 0x1456, because 0x1400 | 0x456 = 0x1456. 76 assertEquals("View visibility should be 0x1456", 0x1456, view.getSystemUiVisibility()); 77 } 78 } 79 80 @UiThreadTest 81 @Test 82 public void testRemoveVisibilityFlagView() { 83 final View view = createViewWithSystemUiVisibility(0x456); 84 SystemBarHelper.removeVisibilityFlag(view, 0x1400); 85 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 86 // Check that result is 0x56, because 0x456 & ~0x1400 = 0x56. 87 assertEquals("View visibility should be 0x56", 0x56, view.getSystemUiVisibility()); 88 } 89 } 90 91 @UiThreadTest 92 @Test 93 public void testAddVisibilityFlagWindow() { 94 final Window window = createWindowWithSystemUiVisibility(0x456); 95 SystemBarHelper.addVisibilityFlag(window, 0x1400); 96 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 97 // Check that result is 0x1456 = 0x1400 | 0x456. 98 assertEquals("View visibility should be 0x1456", 0x1456, 99 window.getAttributes().systemUiVisibility); 100 } 101 } 102 103 @UiThreadTest 104 @Test 105 public void testRemoveVisibilityFlagWindow() { 106 final Window window = createWindowWithSystemUiVisibility(0x456); 107 SystemBarHelper.removeVisibilityFlag(window, 0x1400); 108 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 109 // Check that result is 0x56 = 0x456 & ~0x1400. 110 assertEquals("View visibility should be 0x56", 0x56, 111 window.getAttributes().systemUiVisibility); 112 } 113 } 114 115 @UiThreadTest 116 @Test 117 public void testHideSystemBarsWindow() { 118 final Window window = createWindowWithSystemUiVisibility(0x456); 119 SystemBarHelper.hideSystemBars(window); 120 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 121 assertEquals("DEFAULT_IMMERSIVE_FLAGS should be added to window's systemUiVisibility", 122 DEFAULT_IMMERSIVE_FLAGS | 0x456, 123 window.getAttributes().systemUiVisibility); 124 assertEquals( 125 "DEFAULT_IMMERSIVE_FLAGS should be added to decorView's systemUiVisibility", 126 DEFAULT_IMMERSIVE_FLAGS | 0x456, 127 window.getDecorView().getSystemUiVisibility()); 128 assertEquals("Navigation bar should be transparent", window.getNavigationBarColor(), 0); 129 assertEquals("Status bar should be transparent", window.getStatusBarColor(), 0); 130 } 131 } 132 133 @UiThreadTest 134 @Test 135 public void testShowSystemBarsWindow() { 136 final Window window = createWindowWithSystemUiVisibility(0x456); 137 Context context = new ContextThemeWrapper( 138 InstrumentationRegistry.getContext(), android.R.style.Theme); 139 SystemBarHelper.showSystemBars(window, context); 140 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 141 assertEquals( 142 "DEFAULT_IMMERSIVE_FLAGS should be removed from window's systemUiVisibility", 143 0x456 & ~DEFAULT_IMMERSIVE_FLAGS, 144 window.getAttributes().systemUiVisibility); 145 assertEquals( 146 "DEFAULT_IMMERSIVE_FLAGS should be removed from decorView's systemUiVisibility", 147 0x456 & ~DEFAULT_IMMERSIVE_FLAGS, 148 window.getDecorView().getSystemUiVisibility()); 149 assertEquals("Navigation bar should not be transparent", 150 window.getNavigationBarColor(), 0xff000000); 151 assertEquals("Status bar should not be transparent", 152 window.getStatusBarColor(), 0xff000000); 153 } 154 } 155 156 @UiThreadTest 157 @Test 158 public void testHideSystemBarsNoInfiniteLoop() throws InterruptedException { 159 final TestWindow window = new TestWindow(InstrumentationRegistry.getContext(), null); 160 final HandlerThread thread = new HandlerThread("SystemBarHelperTest"); 161 thread.start(); 162 final Handler handler = new Handler(thread.getLooper()); 163 handler.post(new Runnable() { 164 @Override 165 public void run() { 166 SystemBarHelper.hideSystemBars(window); 167 } 168 }); 169 SystemClock.sleep(500); // Wait for the looper to drain all the messages 170 thread.quit(); 171 // Initial peek + 3 retries = 4 tries total 172 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 173 assertEquals("Peek decor view should give up after 4 tries", 4, 174 window.peekDecorViewCount); 175 } 176 } 177 178 @UiThreadTest 179 @Test 180 public void testHideSystemBarsDialog() { 181 final Dialog dialog = new Dialog(InstrumentationRegistry.getContext()); 182 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 183 final WindowManager.LayoutParams attrs = dialog.getWindow().getAttributes(); 184 attrs.systemUiVisibility = 0x456; 185 dialog.getWindow().setAttributes(attrs); 186 } 187 188 SystemBarHelper.hideSystemBars(dialog); 189 if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { 190 assertEquals("DIALOG_IMMERSIVE_FLAGS should be added to window's systemUiVisibility", 191 DIALOG_IMMERSIVE_FLAGS | 0x456, 192 dialog.getWindow().getAttributes().systemUiVisibility); 193 } 194 } 195 196 @UiThreadTest 197 @Test 198 public void testSetBackButtonVisibleTrue() { 199 final Window window = createWindowWithSystemUiVisibility(STATUS_BAR_DISABLE_BACK | 0x456); 200 SystemBarHelper.setBackButtonVisible(window, true); 201 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 202 assertThat(window.getAttributes().systemUiVisibility) 203 .named("window sysUiVisibility") 204 .isEqualTo(0x456); 205 assertThat(window.getDecorView().getSystemUiVisibility()) 206 .named("decor view sysUiVisibility") 207 .isEqualTo(0x456); 208 } 209 } 210 211 @UiThreadTest 212 @Test 213 public void testSetBackButtonVisibleFalse() { 214 final Window window = createWindowWithSystemUiVisibility(0x456); 215 SystemBarHelper.setBackButtonVisible(window, false); 216 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 217 assertThat(window.getAttributes().systemUiVisibility) 218 .named("window sysUiVisibility") 219 .isEqualTo(0x456 | STATUS_BAR_DISABLE_BACK); 220 assertThat(window.getDecorView().getSystemUiVisibility()) 221 .named("decor view sysUiVisibility") 222 .isEqualTo(0x456 | STATUS_BAR_DISABLE_BACK); 223 } 224 } 225 226 private View createViewWithSystemUiVisibility(int vis) { 227 final View view = new View(InstrumentationRegistry.getContext()); 228 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 229 view.setSystemUiVisibility(vis); 230 } 231 return view; 232 } 233 234 private Window createWindowWithSystemUiVisibility(int vis) { 235 final Window window = new TestWindow(InstrumentationRegistry.getContext(), 236 createViewWithSystemUiVisibility(vis)); 237 if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB) { 238 WindowManager.LayoutParams attrs = window.getAttributes(); 239 attrs.systemUiVisibility = vis; 240 window.setAttributes(attrs); 241 } 242 return window; 243 } 244 245 private static class TestWindow extends MockWindow { 246 247 private View mDecorView; 248 public int peekDecorViewCount = 0; 249 250 private int mNavigationBarColor = -1; 251 private int mStatusBarColor = -1; 252 253 TestWindow(Context context, View decorView) { 254 super(context); 255 mDecorView = decorView; 256 } 257 258 @Override 259 public View getDecorView() { 260 return mDecorView; 261 } 262 263 @Override 264 public View peekDecorView() { 265 peekDecorViewCount++; 266 return mDecorView; 267 } 268 269 @Override 270 public void setNavigationBarColor(int i) { 271 mNavigationBarColor = i; 272 } 273 274 @Override 275 public int getNavigationBarColor() { 276 return mNavigationBarColor; 277 } 278 279 @Override 280 public void setStatusBarColor(int i) { 281 mStatusBarColor = i; 282 } 283 284 @Override 285 public int getStatusBarColor() { 286 return mStatusBarColor; 287 } 288 } 289 } 290