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 |