| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.compositor; | 5 package org.chromium.chrome.browser.compositor; |
| 6 | 6 |
| 7 import android.app.Activity; | 7 import android.app.Activity; |
| 8 import android.graphics.PixelFormat; | 8 import android.graphics.PixelFormat; |
| 9 import android.view.Surface; | 9 import android.view.Surface; |
| 10 import android.view.SurfaceHolder; | 10 import android.view.SurfaceHolder; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 @RunWith(LocalRobolectricTestRunner.class) | 46 @RunWith(LocalRobolectricTestRunner.class) |
| 47 @Config(manifest = Config.NONE) | 47 @Config(manifest = Config.NONE) |
| 48 public class CompositorSurfaceManagerTest { | 48 public class CompositorSurfaceManagerTest { |
| 49 @Mock | 49 @Mock |
| 50 private CompositorSurfaceManager.SurfaceHolderCallbackTarget mCallback; | 50 private CompositorSurfaceManager.SurfaceHolderCallbackTarget mCallback; |
| 51 | 51 |
| 52 private CompositorSurfaceManager mManager; | 52 private CompositorSurfaceManager mManager; |
| 53 | 53 |
| 54 private FrameLayout mLayout; | 54 private FrameLayout mLayout; |
| 55 | 55 |
| 56 // surfaceChanged parameters chosen by most recent sendSurfaceChanged. |
| 57 private int mActualFormat; |
| 58 private int mWidth; |
| 59 private int mHeight; |
| 60 |
| 56 /** | 61 /** |
| 57 * Implementation of a SurfaceView shadow that provides additional functiona
lity for controlling | 62 * Implementation of a SurfaceView shadow that provides additional functiona
lity for controlling |
| 58 * the state of the underlying (fake) Surface. | 63 * the state of the underlying (fake) Surface. |
| 59 */ | 64 */ |
| 60 @Implements(SurfaceView.class) | 65 @Implements(SurfaceView.class) |
| 61 public static class MyShadowSurfaceView extends ShadowSurfaceView { | 66 public static class MyShadowSurfaceView extends ShadowSurfaceView { |
| 62 private final MyFakeSurfaceHolder mHolder = new MyFakeSurfaceHolder(); | 67 private final MyFakeSurfaceHolder mHolder = new MyFakeSurfaceHolder(); |
| 63 | 68 |
| 64 /** | 69 /** |
| 65 * Robolectric's FakeSurfaceHolder doesn't keep track of the format, etc
. | 70 * Robolectric's FakeSurfaceHolder doesn't keep track of the format, etc
. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 } | 184 } |
| 180 | 185 |
| 181 /** | 186 /** |
| 182 * Request format |format|, and send created / changed callbacks to |mManage
r| as if Android | 187 * Request format |format|, and send created / changed callbacks to |mManage
r| as if Android |
| 183 * had provided the underlying Surface. | 188 * had provided the underlying Surface. |
| 184 */ | 189 */ |
| 185 private SurfaceView requestThenCreateSurface(int format) { | 190 private SurfaceView requestThenCreateSurface(int format) { |
| 186 SurfaceView view = requestSurface(format); | 191 SurfaceView view = requestSurface(format); |
| 187 setSurfaceValid(view, true); | 192 setSurfaceValid(view, true); |
| 188 callbackFor(view).surfaceCreated(view.getHolder()); | 193 callbackFor(view).surfaceCreated(view.getHolder()); |
| 189 final int actualFormat = | 194 sendSurfaceChanged(view, format, 320, 240); |
| 190 (format == PixelFormat.OPAQUE) ? PixelFormat.RGB_565 : PixelForm
at.RGBA_8888; | |
| 191 final int width = 320; | |
| 192 final int height = 240; | |
| 193 callbackFor(view).surfaceChanged(view.getHolder(), actualFormat, width,
height); | |
| 194 | 195 |
| 195 return view; | 196 return view; |
| 196 } | 197 } |
| 197 | 198 |
| 199 /** |
| 200 * Send a surfaceChanged event with the given parameters. |
| 201 */ |
| 202 private void sendSurfaceChanged(SurfaceView view, int format, int width, int
height) { |
| 203 mActualFormat = |
| 204 (format == PixelFormat.OPAQUE) ? PixelFormat.RGB_565 : PixelForm
at.RGBA_8888; |
| 205 mWidth = width; |
| 206 mHeight = height; |
| 207 callbackFor(view).surfaceChanged(view.getHolder(), mActualFormat, mWidth
, mHeight); |
| 208 } |
| 209 |
| 198 @Test | 210 @Test |
| 199 @Feature("Compositor") | 211 @Feature("Compositor") |
| 200 @Config(shadows = {MyShadowSurfaceView.class}) | 212 @Config(shadows = {MyShadowSurfaceView.class}) |
| 201 public void testRequestOpaqueSurface() { | 213 public void testRequestOpaqueSurface() { |
| 202 // Request a SurfaceView, and test in detail that it worked. | 214 // Request a SurfaceView, and test in detail that it worked. |
| 203 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); | 215 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); |
| 204 verify(mCallback, times(0)).surfaceCreated(ArgumentMatchers.<SurfaceHold
er>any()); | 216 verify(mCallback, times(0)).surfaceCreated(ArgumentMatchers.<SurfaceHold
er>any()); |
| 205 verify(mCallback, times(0)) | 217 verify(mCallback, times(0)) |
| 206 .surfaceChanged( | 218 .surfaceChanged( |
| 207 ArgumentMatchers.<SurfaceHolder>any(), anyInt(), anyInt(
), anyInt()); | 219 ArgumentMatchers.<SurfaceHolder>any(), anyInt(), anyInt(
), anyInt()); |
| 208 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); | 220 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); |
| 209 | 221 |
| 210 // Check that there's an opaque SurfaceView . | 222 // Check that there's an opaque SurfaceView . |
| 211 assertEquals(1, mLayout.getChildCount()); | 223 assertEquals(1, mLayout.getChildCount()); |
| 212 assertTrue(fakeHolderFor(opaque).getFormat() == PixelFormat.OPAQUE); | 224 assertTrue(fakeHolderFor(opaque).getFormat() == PixelFormat.OPAQUE); |
| 213 | 225 |
| 214 // Verify that we are notified when the surface is created. | 226 // Verify that we are notified when the surface is created. |
| 215 callbackFor(opaque).surfaceCreated(opaque.getHolder()); | 227 callbackFor(opaque).surfaceCreated(opaque.getHolder()); |
| 216 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | 228 verify(mCallback, times(1)).surfaceCreated(eq(opaque.getHolder())); |
| 217 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); | 229 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); |
| 218 | 230 |
| 219 // Verify that we are notified when the surface is changed. | 231 // Verify that we are notified when the surface is changed. |
| 220 final int format = PixelFormat.RGB_565; | 232 sendSurfaceChanged(opaque, PixelFormat.OPAQUE, 320, 240); |
| 221 final int width = 320; | 233 verify(mCallback, times(1)).surfaceCreated(eq(opaque.getHolder())); |
| 222 final int height = 240; | 234 verify(mCallback, times(1)) |
| 223 callbackFor(opaque).surfaceChanged(opaque.getHolder(), format, width, he
ight); | 235 .surfaceChanged(eq(opaque.getHolder()), eq(mActualFormat), eq(mW
idth), eq(mHeight)); |
| 224 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | |
| 225 verify(mCallback, times(1)).surfaceChanged(opaque.getHolder(), format, w
idth, height); | |
| 226 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); | 236 verify(mCallback, times(0)).surfaceDestroyed(ArgumentMatchers.<SurfaceHo
lder>any()); |
| 227 | 237 |
| 228 // Verify that we are notified when the surface is destroyed. | 238 // Verify that we are notified when the surface is destroyed. |
| 229 callbackFor(opaque).surfaceDestroyed(opaque.getHolder()); | 239 callbackFor(opaque).surfaceDestroyed(opaque.getHolder()); |
| 230 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | 240 verify(mCallback, times(1)).surfaceCreated(eq(opaque.getHolder())); |
| 231 verify(mCallback, times(1)).surfaceChanged(opaque.getHolder(), format, w
idth, height); | 241 verify(mCallback, times(1)) |
| 232 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); | 242 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); |
| 243 verify(mCallback, times(1)).surfaceDestroyed(eq(opaque.getHolder())); |
| 233 } | 244 } |
| 234 | 245 |
| 235 @Test | 246 @Test |
| 236 @Feature("Compositor") | 247 @Feature("Compositor") |
| 237 @Config(shadows = {MyShadowSurfaceView.class}) | 248 @Config(shadows = {MyShadowSurfaceView.class}) |
| 238 public void testRequestOpaqueThenTranslucentSurface() { | 249 public void testRequestOpaqueThenTranslucentSurface() { |
| 239 // Request opaque then translucent. | 250 // Request opaque then translucent. |
| 240 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); | 251 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); |
| 241 SurfaceView translucent = requestThenCreateSurface(PixelFormat.TRANSLUCE
NT); | 252 SurfaceView translucent = requestThenCreateSurface(PixelFormat.TRANSLUCE
NT); |
| 242 | 253 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 256 assertNotNull(findSurface(PixelFormat.TRANSLUCENT)); | 267 assertNotNull(findSurface(PixelFormat.TRANSLUCENT)); |
| 257 } | 268 } |
| 258 | 269 |
| 259 @Test | 270 @Test |
| 260 @Feature("Compositor") | 271 @Feature("Compositor") |
| 261 @Config(shadows = {MyShadowSurfaceView.class}) | 272 @Config(shadows = {MyShadowSurfaceView.class}) |
| 262 public void testRequestSameSurface() { | 273 public void testRequestSameSurface() { |
| 263 // Request an opaque surface, get it, then request it again. Verify tha
t we get synthetic | 274 // Request an opaque surface, get it, then request it again. Verify tha
t we get synthetic |
| 264 // create / destroy callbacks. | 275 // create / destroy callbacks. |
| 265 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); | 276 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); |
| 266 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | 277 verify(mCallback, times(1)).surfaceCreated(eq(opaque.getHolder())); |
| 267 verify(mCallback, times(1)) | 278 verify(mCallback, times(1)) |
| 268 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 279 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); |
| 269 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); | 280 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); |
| 270 | 281 |
| 271 // Surface is curerntly valid. Request again. We should get back a des
troy and create. | 282 // Surface is currently valid. Request again. We should get back a des
troy and create. |
| 272 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); | 283 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); |
| 273 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); | 284 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); |
| 274 verify(mCallback, times(2)) | 285 verify(mCallback, times(2)) |
| 275 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 286 .surfaceChanged(eq(opaque.getHolder()), eq(mActualFormat), eq(mW
idth), eq(mHeight)); |
| 276 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); | 287 verify(mCallback, times(1)).surfaceDestroyed(eq(opaque.getHolder())); |
| 277 assertEquals(1, mLayout.getChildCount()); | 288 assertEquals(1, mLayout.getChildCount()); |
| 278 } | 289 } |
| 279 | 290 |
| 280 @Test | 291 @Test |
| 281 @Feature("Compositor") | 292 @Feature("Compositor") |
| 282 @Config(shadows = {MyShadowSurfaceView.class}) | 293 @Config(shadows = {MyShadowSurfaceView.class}) |
| 283 public void testRequestSameSurfaceBeforeReady() { | 294 public void testRequestSameSurfaceBeforeReady() { |
| 284 // Request an opaque surface, then request it again before the first one
shows up. | 295 // Request an opaque surface, then request it again before the first one
shows up. |
| 285 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); | 296 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); |
| 286 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); | 297 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); |
| 287 verify(mCallback, times(0)) | 298 verify(mCallback, times(0)) |
| 288 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 299 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); |
| 289 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); | 300 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); |
| 290 | 301 |
| 291 // Request again. We shouldn't get any callbacks, since the surface is
still pending. | 302 // Request again. We shouldn't get any callbacks, since the surface is
still pending. |
| 292 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); | 303 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); |
| 293 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); | 304 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); |
| 294 verify(mCallback, times(0)) | 305 verify(mCallback, times(0)) |
| 295 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 306 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); |
| 296 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); | 307 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); |
| 297 | 308 |
| 298 // Only the opaque view should be attached. | 309 // Only the opaque view should be attached. |
| 299 assertEquals(1, mLayout.getChildCount()); | 310 assertEquals(1, mLayout.getChildCount()); |
| 300 | 311 |
| 301 // When the surface is created, we should get notified created / changed
, but not destroyed. | 312 // When the surface is created, we should get notified created / changed
, but not destroyed. |
| 302 callbackFor(opaque).surfaceCreated(opaque.getHolder()); | 313 callbackFor(opaque).surfaceCreated(opaque.getHolder()); |
| 303 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | 314 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); |
| 304 | 315 |
| 305 callbackFor(opaque).surfaceChanged(opaque.getHolder(), PixelFormat.RGB_5
65, 320, 240); | 316 sendSurfaceChanged(opaque, PixelFormat.RGB_565, 320, 240); |
| 306 verify(mCallback, times(1)) | 317 verify(mCallback, times(1)) |
| 307 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 318 .surfaceChanged(eq(opaque.getHolder()), eq(mActualFormat), eq(mW
idth), eq(mHeight)); |
| 308 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); | 319 verify(mCallback, times(0)).surfaceDestroyed(opaque.getHolder()); |
| 309 } | 320 } |
| 310 | 321 |
| 311 @Test | 322 @Test |
| 312 @Feature("Compositor") | 323 @Feature("Compositor") |
| 313 @Config(shadows = {MyShadowSurfaceView.class}) | 324 @Config(shadows = {MyShadowSurfaceView.class}) |
| 314 public void testRequestDifferentSurfacesBeforeReady() { | 325 public void testRequestDifferentSurfacesBeforeReady() { |
| 315 // Request an opaque surface, then request the translucent one before th
e it one shows up. | 326 // Request an opaque surface, then request the translucent one before th
e it one shows up. |
| 316 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); | 327 SurfaceView opaque = requestSurface(PixelFormat.OPAQUE); |
| 317 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); | 328 verify(mCallback, times(0)).surfaceCreated(opaque.getHolder()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 | 368 |
| 358 // Re-request while 'changed' is still pending. We should get a synthet
ic 'destroyed' and | 369 // Re-request while 'changed' is still pending. We should get a synthet
ic 'destroyed' and |
| 359 // synthetic 'created'. | 370 // synthetic 'created'. |
| 360 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); | 371 assertEquals(opaque, requestSurface(PixelFormat.OPAQUE)); |
| 361 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); | 372 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); |
| 362 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); | 373 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); |
| 363 verify(mCallback, times(0)) | 374 verify(mCallback, times(0)) |
| 364 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 375 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); |
| 365 | 376 |
| 366 // Send 'changed', and expect that we'll receive it. | 377 // Send 'changed', and expect that we'll receive it. |
| 367 callbackFor(opaque).surfaceChanged(opaque.getHolder(), PixelFormat.RGB_5
65, 320, 240); | 378 sendSurfaceChanged(opaque, PixelFormat.OPAQUE, 320, 240); |
| 368 verify(mCallback, times(1)) | 379 verify(mCallback, times(1)) |
| 369 .surfaceChanged(eq(opaque.getHolder()), anyInt(), anyInt(), anyI
nt()); | 380 .surfaceChanged(eq(opaque.getHolder()), eq(mActualFormat), eq(mW
idth), eq(mHeight)); |
| 370 } | 381 } |
| 371 | 382 |
| 372 @Test | 383 @Test |
| 373 @Feature("Compositor") | 384 @Feature("Compositor") |
| 374 @Config(shadows = {MyShadowSurfaceView.class}) | 385 @Config(shadows = {MyShadowSurfaceView.class}) |
| 375 public void testJellyBeanWorkaround() { | 386 public void testJellyBeanWorkaround() { |
| 376 // See if recreateSurfaceForJellyBean destroys / re-creates the surface. | 387 // See if recreateSurfaceForJellyBean destroys / re-creates the surface. |
| 377 // should get a synthetic 'created', but a real 'changed' callback. | 388 // should get a synthetic 'created', but a real 'changed' callback. |
| 378 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); | 389 SurfaceView opaque = requestThenCreateSurface(PixelFormat.OPAQUE); |
| 379 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); | 390 verify(mCallback, times(1)).surfaceCreated(opaque.getHolder()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 | 442 |
| 432 // When the opaque surface becomes available, we'll get the synthetic de
stroy for the | 443 // When the opaque surface becomes available, we'll get the synthetic de
stroy for the |
| 433 // translucent one that we lost ownership of, and the real create for th
e opaque one. | 444 // translucent one that we lost ownership of, and the real create for th
e opaque one. |
| 434 callbackFor(opaque).surfaceCreated(opaque.getHolder()); | 445 callbackFor(opaque).surfaceCreated(opaque.getHolder()); |
| 435 assertEquals(2, mLayout.getChildCount()); | 446 assertEquals(2, mLayout.getChildCount()); |
| 436 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); | 447 verify(mCallback, times(2)).surfaceCreated(opaque.getHolder()); |
| 437 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); | 448 verify(mCallback, times(1)).surfaceDestroyed(opaque.getHolder()); |
| 438 verify(mCallback, times(1)).surfaceDestroyed(translucent.getHolder()); | 449 verify(mCallback, times(1)).surfaceDestroyed(translucent.getHolder()); |
| 439 } | 450 } |
| 440 } | 451 } |
| OLD | NEW |