1/* 2 * Copyright (C) 2018 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 17package com.android.internal.widget; 18 19import static android.view.View.VISIBLE; 20 21import static org.hamcrest.Matchers.is; 22import static org.junit.Assert.assertThat; 23import static org.mockito.ArgumentMatchers.any; 24import static org.mockito.Mockito.atLeastOnce; 25import static org.mockito.Mockito.mock; 26import static org.mockito.Mockito.verify; 27import static org.mockito.Mockito.verifyNoMoreInteractions; 28 29import static java.util.Arrays.asList; 30import static java.util.Collections.emptyList; 31 32import android.graphics.Color; 33import android.graphics.drawable.ColorDrawable; 34import android.graphics.drawable.Drawable; 35import android.support.test.InstrumentationRegistry; 36import android.view.ViewGroup; 37import android.widget.FrameLayout; 38 39import org.junit.Before; 40import org.junit.Test; 41 42import java.util.List; 43 44public class BackgroundFallbackTest { 45 46 private static final int NAVBAR_BOTTOM = 0; 47 private static final int NAVBAR_LEFT = 1; 48 private static final int NAVBAR_RIGHT = 2; 49 50 private static final int SCREEN_HEIGHT = 2000; 51 private static final int SCREEN_WIDTH = 1000; 52 private static final int STATUS_HEIGHT = 100; 53 private static final int NAV_SIZE = 200; 54 55 private static final boolean INSET_CONTENT_VIEWS = true; 56 private static final boolean DONT_INSET_CONTENT_VIEWS = false; 57 58 BackgroundFallback mFallback; 59 Drawable mDrawableMock; 60 61 ViewGroup mStatusBarView; 62 ViewGroup mNavigationBarView; 63 64 ViewGroup mDecorViewMock; 65 ViewGroup mContentRootMock; 66 ViewGroup mContentContainerMock; 67 ViewGroup mContentMock; 68 69 int mLastTop = 0; 70 71 @Before 72 public void setUp() throws Exception { 73 mFallback = new BackgroundFallback(); 74 mDrawableMock = mock(Drawable.class); 75 76 mFallback.setDrawable(mDrawableMock); 77 78 } 79 80 @Test 81 public void hasFallback_withDrawable_true() { 82 mFallback.setDrawable(mDrawableMock); 83 assertThat(mFallback.hasFallback(), is(true)); 84 } 85 86 @Test 87 public void hasFallback_withoutDrawable_false() { 88 mFallback.setDrawable(null); 89 assertThat(mFallback.hasFallback(), is(false)); 90 } 91 92 @Test 93 public void draw_portrait_noFallback() { 94 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM); 95 96 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 97 mStatusBarView, mNavigationBarView); 98 99 verifyNoMoreInteractions(mDrawableMock); 100 } 101 102 @Test 103 public void draw_portrait_translucentBars_fallback() { 104 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_BOTTOM); 105 setTranslucent(mStatusBarView); 106 setTranslucent(mNavigationBarView); 107 108 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 109 mStatusBarView, mNavigationBarView); 110 111 verifyFallbackTop(STATUS_HEIGHT); 112 verifyFallbackBottom(NAV_SIZE); 113 verifyNoMoreInteractions(mDrawableMock); 114 } 115 116 @Test 117 public void draw_landscape_translucentBars_fallback() { 118 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT); 119 setTranslucent(mStatusBarView); 120 setTranslucent(mNavigationBarView); 121 122 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 123 mStatusBarView, mNavigationBarView); 124 125 verifyFallbackTop(STATUS_HEIGHT); 126 verifyFallbackRight(NAV_SIZE); 127 verifyNoMoreInteractions(mDrawableMock); 128 } 129 130 @Test 131 public void draw_seascape_translucentBars_fallback() { 132 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT); 133 setTranslucent(mStatusBarView); 134 setTranslucent(mNavigationBarView); 135 136 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 137 mStatusBarView, mNavigationBarView); 138 139 verifyFallbackTop(STATUS_HEIGHT); 140 verifyFallbackLeft(NAV_SIZE); 141 verifyNoMoreInteractions(mDrawableMock); 142 } 143 144 @Test 145 public void draw_landscape_noFallback() { 146 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_RIGHT); 147 148 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 149 mStatusBarView, mNavigationBarView); 150 151 verifyNoMoreInteractions(mDrawableMock); 152 } 153 154 @Test 155 public void draw_seascape_noFallback() { 156 setUpViewHierarchy(INSET_CONTENT_VIEWS, NAVBAR_LEFT); 157 158 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 159 mStatusBarView, mNavigationBarView); 160 161 verifyNoMoreInteractions(mDrawableMock); 162 } 163 164 @Test 165 public void draw_seascape_translucentBars_noInsets_noFallback() { 166 setUpViewHierarchy(DONT_INSET_CONTENT_VIEWS, NAVBAR_LEFT); 167 setTranslucent(mStatusBarView); 168 setTranslucent(mNavigationBarView); 169 170 mFallback.draw(mDecorViewMock, mContentRootMock, null /* canvas */, mContentContainerMock, 171 mStatusBarView, mNavigationBarView); 172 173 verifyNoMoreInteractions(mDrawableMock); 174 } 175 176 private void verifyFallbackTop(int size) { 177 verify(mDrawableMock).setBounds(0, 0, SCREEN_WIDTH, size); 178 verify(mDrawableMock, atLeastOnce()).draw(any()); 179 mLastTop = size; 180 } 181 182 private void verifyFallbackLeft(int size) { 183 verify(mDrawableMock).setBounds(0, mLastTop, size, SCREEN_HEIGHT); 184 verify(mDrawableMock, atLeastOnce()).draw(any()); 185 } 186 187 private void verifyFallbackRight(int size) { 188 verify(mDrawableMock).setBounds(SCREEN_WIDTH - size, mLastTop, SCREEN_WIDTH, SCREEN_HEIGHT); 189 verify(mDrawableMock, atLeastOnce()).draw(any()); 190 } 191 192 private void verifyFallbackBottom(int size) { 193 verify(mDrawableMock).setBounds(0, SCREEN_HEIGHT - size, SCREEN_WIDTH, SCREEN_HEIGHT); 194 verify(mDrawableMock, atLeastOnce()).draw(any()); 195 } 196 197 private void setUpViewHierarchy(boolean insetContentViews, int navBarPosition) { 198 int insetLeft = 0; 199 int insetTop = 0; 200 int insetRight = 0; 201 int insetBottom = 0; 202 203 mStatusBarView = mockView(0, 0, SCREEN_WIDTH, STATUS_HEIGHT, 204 new ColorDrawable(Color.BLACK), VISIBLE, emptyList()); 205 if (insetContentViews) { 206 insetTop = STATUS_HEIGHT; 207 } 208 209 switch (navBarPosition) { 210 case NAVBAR_BOTTOM: 211 mNavigationBarView = mockView(0, SCREEN_HEIGHT - NAV_SIZE, SCREEN_WIDTH, 212 SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList()); 213 if (insetContentViews) { 214 insetBottom = NAV_SIZE; 215 } 216 break; 217 case NAVBAR_LEFT: 218 mNavigationBarView = mockView(0, 0, NAV_SIZE, SCREEN_HEIGHT, 219 new ColorDrawable(Color.BLACK), VISIBLE, emptyList()); 220 if (insetContentViews) { 221 insetLeft = NAV_SIZE; 222 } 223 break; 224 case NAVBAR_RIGHT: 225 mNavigationBarView = mockView(SCREEN_WIDTH - NAV_SIZE, 0, SCREEN_WIDTH, 226 SCREEN_HEIGHT, new ColorDrawable(Color.BLACK), VISIBLE, emptyList()); 227 if (insetContentViews) { 228 insetRight = NAV_SIZE; 229 } 230 break; 231 } 232 233 mContentMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight, 234 SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, emptyList()); 235 mContentContainerMock = mockView(0, 0, SCREEN_WIDTH - insetLeft - insetRight, 236 SCREEN_HEIGHT - insetTop - insetBottom, null, VISIBLE, asList(mContentMock)); 237 mContentRootMock = mockView(insetLeft, insetTop, SCREEN_WIDTH - insetRight, 238 SCREEN_HEIGHT - insetBottom, null, VISIBLE, asList(mContentContainerMock)); 239 240 mDecorViewMock = mockView(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null, VISIBLE, 241 asList(mContentRootMock, mStatusBarView, mNavigationBarView)); 242 } 243 244 private void setTranslucent(ViewGroup bar) { 245 bar.setBackground(new ColorDrawable(Color.TRANSPARENT)); 246 } 247 248 private ViewGroup mockView(int left, int top, int right, int bottom, Drawable background, 249 int visibility, List<ViewGroup> children) { 250 final ViewGroup v = new FrameLayout(InstrumentationRegistry.getTargetContext()); 251 252 v.layout(left, top, right, bottom); 253 v.setBackground(background); 254 v.setVisibility(visibility); 255 256 for (ViewGroup c : children) { 257 v.addView(c); 258 } 259 260 return v; 261 } 262}