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 17 package com.android.systemui.wallpapers; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import static org.hamcrest.Matchers.equalTo; 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyBoolean; 25 import static org.mockito.Mockito.clearInvocations; 26 import static org.mockito.Mockito.doAnswer; 27 import static org.mockito.Mockito.doNothing; 28 import static org.mockito.Mockito.eq; 29 import static org.mockito.Mockito.spy; 30 import static org.mockito.Mockito.times; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 import static org.mockito.hamcrest.MockitoHamcrest.intThat; 34 35 import android.app.ActivityManager; 36 import android.app.WallpaperManager; 37 import android.content.Context; 38 import android.graphics.Bitmap; 39 import android.graphics.ColorSpace; 40 import android.graphics.Rect; 41 import android.hardware.display.DisplayManager; 42 import android.testing.AndroidTestingRunner; 43 import android.testing.TestableLooper; 44 import android.view.Surface; 45 import android.view.SurfaceHolder; 46 import android.view.WindowManager; 47 import android.view.WindowMetrics; 48 49 import androidx.test.filters.SmallTest; 50 51 import com.android.systemui.SysuiTestCase; 52 import com.android.systemui.settings.UserTracker; 53 import com.android.systemui.util.concurrency.FakeExecutor; 54 import com.android.systemui.util.time.FakeSystemClock; 55 56 import org.junit.Before; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Mock; 60 import org.mockito.MockitoAnnotations; 61 62 @SmallTest 63 @RunWith(AndroidTestingRunner.class) 64 @TestableLooper.RunWithLooper 65 public class ImageWallpaperTest extends SysuiTestCase { 66 private static final int LOW_BMP_WIDTH = 128; 67 private static final int LOW_BMP_HEIGHT = 128; 68 private static final int DISPLAY_WIDTH = 1920; 69 private static final int DISPLAY_HEIGHT = 1080; 70 71 @Mock 72 private WindowManager mWindowManager; 73 @Mock 74 private WindowMetrics mWindowMetrics; 75 @Mock 76 private DisplayManager mDisplayManager; 77 @Mock 78 private WallpaperManager mWallpaperManager; 79 @Mock 80 private SurfaceHolder mSurfaceHolder; 81 @Mock 82 private Surface mSurface; 83 @Mock 84 private Context mMockContext; 85 @Mock 86 private UserTracker mUserTracker; 87 88 @Mock 89 private Bitmap mWallpaperBitmap; 90 FakeSystemClock mFakeSystemClock = new FakeSystemClock(); 91 FakeExecutor mFakeExecutor = new FakeExecutor(mFakeSystemClock); 92 93 @Before setUp()94 public void setUp() throws Exception { 95 allowTestableLooperAsMainThread(); 96 MockitoAnnotations.initMocks(this); 97 //mEventCountdown = new CountDownLatch(1); 98 99 // set up window manager 100 when(mWindowMetrics.getBounds()).thenReturn( 101 new Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT)); 102 when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics); 103 when(mMockContext.getSystemService(WindowManager.class)).thenReturn(mWindowManager); 104 105 // set up display manager 106 doNothing().when(mDisplayManager).registerDisplayListener(any(), any()); 107 when(mMockContext.getSystemService(DisplayManager.class)).thenReturn(mDisplayManager); 108 109 // set up bitmap 110 when(mWallpaperBitmap.getColorSpace()).thenReturn(ColorSpace.get(ColorSpace.Named.SRGB)); 111 when(mWallpaperBitmap.getConfig()).thenReturn(Bitmap.Config.ARGB_8888); 112 113 // set up wallpaper manager 114 when(mWallpaperManager.getBitmapAsUser(eq(ActivityManager.getCurrentUser()), anyBoolean())) 115 .thenReturn(mWallpaperBitmap); 116 when(mMockContext.getSystemService(WallpaperManager.class)).thenReturn(mWallpaperManager); 117 118 // set up surface 119 when(mSurfaceHolder.getSurface()).thenReturn(mSurface); 120 doNothing().when(mSurface).hwuiDestroy(); 121 122 // set up UserTracker 123 when(mUserTracker.getUserId()).thenReturn(ActivityManager.getCurrentUser()); 124 } 125 126 @Test testBitmapWallpaper_normal()127 public void testBitmapWallpaper_normal() { 128 // Will use an image wallpaper with dimensions DISPLAY_WIDTH x DISPLAY_WIDTH. 129 // Then we expect the surface size will be also DISPLAY_WIDTH x DISPLAY_WIDTH. 130 int bitmapSide = DISPLAY_WIDTH; 131 testSurfaceHelper( 132 bitmapSide /* bitmapWidth */, 133 bitmapSide /* bitmapHeight */, 134 bitmapSide /* expectedSurfaceWidth */, 135 bitmapSide /* expectedSurfaceHeight */); 136 } 137 138 @Test testBitmapWallpaper_low_resolution()139 public void testBitmapWallpaper_low_resolution() { 140 // Will use an image wallpaper with dimensions BMP_WIDTH x BMP_HEIGHT. 141 // Then we expect the surface size will be also BMP_WIDTH x BMP_HEIGHT. 142 testSurfaceHelper(LOW_BMP_WIDTH /* bitmapWidth */, 143 LOW_BMP_HEIGHT /* bitmapHeight */, 144 LOW_BMP_WIDTH /* expectedSurfaceWidth */, 145 LOW_BMP_HEIGHT /* expectedSurfaceHeight */); 146 } 147 148 @Test testBitmapWallpaper_too_small()149 public void testBitmapWallpaper_too_small() { 150 151 // test that the surface is always at least MIN_SURFACE_WIDTH x MIN_SURFACE_HEIGHT 152 testMinSurfaceHelper(8, 8); 153 testMinSurfaceHelper(100, 2000); 154 testMinSurfaceHelper(200, 1); 155 } 156 157 @Test testLoadDrawAndUnloadBitmap()158 public void testLoadDrawAndUnloadBitmap() { 159 setBitmapDimensions(LOW_BMP_WIDTH, LOW_BMP_HEIGHT); 160 161 ImageWallpaper.CanvasEngine spyEngine = getSpyEngine(); 162 spyEngine.onCreate(mSurfaceHolder); 163 spyEngine.onSurfaceRedrawNeeded(mSurfaceHolder); 164 assertThat(mFakeExecutor.numPending()).isAtLeast(1); 165 166 int n = 0; 167 while (mFakeExecutor.numPending() >= 1) { 168 n++; 169 assertThat(n).isAtMost(10); 170 mFakeExecutor.runNextReady(); 171 mFakeSystemClock.advanceTime(1000); 172 } 173 174 verify(spyEngine, times(1)).drawFrameOnCanvas(mWallpaperBitmap); 175 assertThat(spyEngine.isBitmapLoaded()).isFalse(); 176 } 177 createImageWallpaper()178 private ImageWallpaper createImageWallpaper() { 179 return new ImageWallpaper(mFakeExecutor, mUserTracker) { 180 @Override 181 public Engine onCreateEngine() { 182 return new CanvasEngine() { 183 @Override 184 public Context getDisplayContext() { 185 return mMockContext; 186 } 187 188 @Override 189 public SurfaceHolder getSurfaceHolder() { 190 return mSurfaceHolder; 191 } 192 193 @Override 194 public void setFixedSizeAllowed(boolean allowed) { 195 super.setFixedSizeAllowed(allowed); 196 assertWithMessage("mFixedSizeAllowed should be true").that( 197 allowed).isTrue(); 198 } 199 }; 200 } 201 }; 202 } 203 204 private ImageWallpaper.CanvasEngine getSpyEngine() { 205 ImageWallpaper imageWallpaper = createImageWallpaper(); 206 ImageWallpaper.CanvasEngine engine = 207 (ImageWallpaper.CanvasEngine) imageWallpaper.onCreateEngine(); 208 ImageWallpaper.CanvasEngine spyEngine = spy(engine); 209 doNothing().when(spyEngine).drawFrameOnCanvas(any(Bitmap.class)); 210 doNothing().when(spyEngine).reportEngineShown(anyBoolean()); 211 doAnswer(invocation -> { 212 ((ImageWallpaper.CanvasEngine) invocation.getMock()).onMiniBitmapUpdated(); 213 return null; 214 }).when(spyEngine).recomputeColorExtractorMiniBitmap(); 215 return spyEngine; 216 } 217 218 private void setBitmapDimensions(int bitmapWidth, int bitmapHeight) { 219 when(mWallpaperManager.peekBitmapDimensions()) 220 .thenReturn(new Rect(0, 0, bitmapWidth, bitmapHeight)); 221 when(mWallpaperBitmap.getWidth()).thenReturn(bitmapWidth); 222 when(mWallpaperBitmap.getHeight()).thenReturn(bitmapHeight); 223 } 224 225 private void testMinSurfaceHelper(int bitmapWidth, int bitmapHeight) { 226 testSurfaceHelper(bitmapWidth, bitmapHeight, 227 Math.max(ImageWallpaper.CanvasEngine.MIN_SURFACE_WIDTH, bitmapWidth), 228 Math.max(ImageWallpaper.CanvasEngine.MIN_SURFACE_HEIGHT, bitmapHeight)); 229 } 230 231 private void testSurfaceHelper(int bitmapWidth, int bitmapHeight, 232 int expectedSurfaceWidth, int expectedSurfaceHeight) { 233 234 clearInvocations(mSurfaceHolder); 235 setBitmapDimensions(bitmapWidth, bitmapHeight); 236 237 ImageWallpaper imageWallpaper = createImageWallpaper(); 238 ImageWallpaper.CanvasEngine engine = 239 (ImageWallpaper.CanvasEngine) imageWallpaper.onCreateEngine(); 240 engine.onCreate(mSurfaceHolder); 241 242 verify(mSurfaceHolder, times(1)).setFixedSize( 243 intThat(equalTo(expectedSurfaceWidth)), 244 intThat(equalTo(expectedSurfaceHeight))); 245 } 246 } 247