1 /*
2  * Copyright 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 android.view.surfacecontrol.cts;
18 
19 import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
20 import static android.view.cts.surfacevalidator.ASurfaceControlTestActivity.RectChecker;
21 import static android.view.cts.surfacevalidator.ASurfaceControlTestActivity.WAIT_TIMEOUT_S;
22 import static android.view.cts.util.ASurfaceControlTestUtils.applyAndDeleteSurfaceTransaction;
23 import static android.view.cts.util.ASurfaceControlTestUtils.createSurfaceTransaction;
24 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_acquire;
25 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_create;
26 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_createFromWindow;
27 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_fromJava;
28 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceControl_release;
29 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_apply;
30 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_create;
31 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_delete;
32 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_fromJava;
33 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_releaseBuffer;
34 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setBuffer;
35 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setDamageRegion;
36 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setDataSpace;
37 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setDesiredHdrHeadroom;
38 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setDesiredPresentTime;
39 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setExtendedRangeBrightness;
40 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setFrameTimeline;
41 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setOnCommitCallback;
42 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setOnCommitCallbackWithoutContext;
43 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setOnCompleteCallback;
44 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setOnCompleteCallbackWithoutContext;
45 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setPosition;
46 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setQuadrantBuffer;
47 import static android.view.cts.util.ASurfaceControlTestUtils.nSurfaceTransaction_setSolidBuffer;
48 import static android.view.cts.util.ASurfaceControlTestUtils.reparent;
49 import static android.view.cts.util.ASurfaceControlTestUtils.setBufferAlpha;
50 import static android.view.cts.util.ASurfaceControlTestUtils.setBufferOpaque;
51 import static android.view.cts.util.ASurfaceControlTestUtils.setBufferTransform;
52 import static android.view.cts.util.ASurfaceControlTestUtils.setColor;
53 import static android.view.cts.util.ASurfaceControlTestUtils.setCrop;
54 import static android.view.cts.util.ASurfaceControlTestUtils.setGeometry;
55 import static android.view.cts.util.ASurfaceControlTestUtils.setPosition;
56 import static android.view.cts.util.ASurfaceControlTestUtils.setScale;
57 import static android.view.cts.util.ASurfaceControlTestUtils.setVisibility;
58 import static android.view.cts.util.ASurfaceControlTestUtils.setZOrder;
59 import static android.view.cts.util.FrameCallbackData.nGetFrameTimelines;
60 
61 import static org.junit.Assert.assertEquals;
62 import static org.junit.Assert.assertThrows;
63 import static org.junit.Assert.assertTrue;
64 import static org.junit.Assume.assumeTrue;
65 
66 import android.graphics.Canvas;
67 import android.graphics.Color;
68 import android.graphics.Rect;
69 import android.hardware.DataSpace;
70 import android.os.SystemClock;
71 import android.os.Trace;
72 import android.platform.test.annotations.RequiresDevice;
73 import android.util.Log;
74 import android.view.Display;
75 import android.view.Surface;
76 import android.view.SurfaceControl;
77 import android.view.SurfaceHolder;
78 import android.view.cts.surfacevalidator.ASurfaceControlTestActivity;
79 import android.view.cts.surfacevalidator.ASurfaceControlTestActivity.PixelChecker;
80 import android.view.cts.surfacevalidator.PixelColor;
81 import android.view.cts.util.ASurfaceControlTestUtils;
82 import android.view.cts.util.FrameCallbackData;
83 import android.view.cts.util.FrameCallbackData.FrameTimeline;
84 
85 import androidx.annotation.NonNull;
86 import androidx.test.ext.junit.rules.ActivityScenarioRule;
87 import androidx.test.filters.LargeTest;
88 import androidx.test.runner.AndroidJUnit4;
89 
90 import com.android.compatibility.common.util.DisableAnimationRule;
91 import com.android.compatibility.common.util.WidgetTestUtils;
92 
93 import org.junit.Assert;
94 import org.junit.Before;
95 import org.junit.Rule;
96 import org.junit.Test;
97 import org.junit.rules.TestName;
98 import org.junit.runner.RunWith;
99 
100 import java.lang.ref.Reference;
101 import java.util.HashSet;
102 import java.util.List;
103 import java.util.Set;
104 import java.util.concurrent.CountDownLatch;
105 import java.util.concurrent.TimeUnit;
106 import java.util.concurrent.atomic.AtomicLong;
107 import java.util.function.Consumer;
108 
109 @LargeTest
110 @RunWith(AndroidJUnit4.class)
111 public class ASurfaceControlTest {
112     private static final String TAG = ASurfaceControlTest.class.getSimpleName();
113     private static final boolean DEBUG = false;
114 
115     private static final int DEFAULT_LAYOUT_WIDTH = 100;
116     private static final int DEFAULT_LAYOUT_HEIGHT = 100;
117     private static final Rect DEFAULT_RECT = new Rect(1, 1, DEFAULT_LAYOUT_WIDTH - 1,
118             DEFAULT_LAYOUT_HEIGHT - 1);
119 
120     private static final PixelColor RED = new PixelColor(Color.RED);
121     private static final PixelColor BLUE = new PixelColor(Color.BLUE);
122     private static final PixelColor MAGENTA = new PixelColor(Color.MAGENTA);
123     private static final PixelColor GREEN = new PixelColor(Color.GREEN);
124     private static final PixelColor YELLOW = new PixelColor(Color.YELLOW);
125 
126     @Rule
127     public DisableAnimationRule mDisableAnimationRule = new DisableAnimationRule();
128 
129     @Rule
130     public ActivityScenarioRule<ASurfaceControlTestActivity> mActivityRule =
131             createFullscreenActivityScenarioRule(ASurfaceControlTestActivity.class);
132 
133     @Rule
134     public TestName mName = new TestName();
135 
136     private ASurfaceControlTestActivity mActivity;
137 
138     private long mDesiredPresentTime;
139 
140     @Before
setup()141     public void setup() {
142         mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
143     }
144 
145     ///////////////////////////////////////////////////////////////////////////
146     // SurfaceHolder.Callbacks
147     ///////////////////////////////////////////////////////////////////////////
148 
149     private static class SurfaceHolderCallback implements SurfaceHolder.Callback {
150         BasicSurfaceHolderCallback mBasicSurfaceHolderCallback;
151 
SurfaceHolderCallback(BasicSurfaceHolderCallback basicSurfaceHolderCallback)152         SurfaceHolderCallback(BasicSurfaceHolderCallback basicSurfaceHolderCallback) {
153             mBasicSurfaceHolderCallback = basicSurfaceHolderCallback;
154         }
155 
156         @Override
surfaceCreated(@onNull SurfaceHolder holder)157         public void surfaceCreated(@NonNull SurfaceHolder holder) {
158             Canvas canvas = holder.lockCanvas();
159             canvas.drawColor(Color.YELLOW);
160             holder.unlockCanvasAndPost(canvas);
161 
162             mBasicSurfaceHolderCallback.surfaceCreated(holder);
163         }
164 
165         @Override
surfaceChanged(@onNull SurfaceHolder holder, int format, int width, int height)166         public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width,
167                 int height) {
168         }
169 
170         @Override
surfaceDestroyed(@onNull SurfaceHolder holder)171         public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
172             mBasicSurfaceHolderCallback.surfaceDestroyed();
173         }
174     }
175 
176     private abstract static class BasicSurfaceHolderCallback {
177         private final Set<Long> mSurfaceControls = new HashSet<>();
178         private final Set<Long> mBuffers = new HashSet<>();
179 
surfaceCreated(SurfaceHolder surfaceHolder)180         public abstract void surfaceCreated(SurfaceHolder surfaceHolder);
181 
surfaceDestroyed()182         public void surfaceDestroyed() {
183             for (Long surfaceControl : mSurfaceControls) {
184                 reparent(surfaceControl, 0);
185                 nSurfaceControl_release(surfaceControl);
186             }
187             mSurfaceControls.clear();
188 
189             for (Long buffer : mBuffers) {
190                 nSurfaceTransaction_releaseBuffer(buffer);
191             }
192             mBuffers.clear();
193         }
194 
createFromWindow(Surface surface)195         public long createFromWindow(Surface surface) {
196             long surfaceControl = nSurfaceControl_createFromWindow(surface);
197             assertTrue("failed to create surface control", surfaceControl != 0);
198 
199             mSurfaceControls.add(surfaceControl);
200             return surfaceControl;
201         }
202 
create(long parentSurfaceControl)203         public long create(long parentSurfaceControl) {
204             long childSurfaceControl = nSurfaceControl_create(parentSurfaceControl);
205             assertTrue("failed to create child surface control", childSurfaceControl != 0);
206 
207             mSurfaceControls.add(childSurfaceControl);
208             return childSurfaceControl;
209         }
210 
setSolidBuffer( long surfaceControl, long surfaceTransaction, int width, int height, int color)211         public long setSolidBuffer(
212                 long surfaceControl, long surfaceTransaction, int width, int height, int color) {
213             long buffer = nSurfaceTransaction_setSolidBuffer(surfaceControl, surfaceTransaction,
214                     width, height, color);
215             assertTrue("failed to set buffer", buffer != 0);
216             mBuffers.add(buffer);
217             return buffer;
218         }
219 
setSolidBuffer(long surfaceControl, int width, int height, int color)220         public long setSolidBuffer(long surfaceControl, int width, int height, int color) {
221             long surfaceTransaction = createSurfaceTransaction();
222             long buffer = setSolidBuffer(surfaceControl, surfaceTransaction, width, height, color);
223             TimedTransactionListener onCommitCallback = new TimedTransactionListener();
224             nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
225             applyAndDeleteSurfaceTransaction(surfaceTransaction);
226             try {
227                 onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
228             } catch (InterruptedException e) {
229             }
230             if (onCommitCallback.mLatch.getCount() > 0) {
231                 Log.e(TAG, "Failed to wait for commit callback");
232             }
233             return buffer;
234         }
235 
setNullBuffer(long surfaceControl)236         public void setNullBuffer(long surfaceControl) {
237             long surfaceTransaction = createSurfaceTransaction();
238             nSurfaceTransaction_setBuffer(surfaceControl, surfaceTransaction, 0 /* buffer */);
239             TimedTransactionListener onCommitCallback = new TimedTransactionListener();
240             nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
241             applyAndDeleteSurfaceTransaction(surfaceTransaction);
242             try {
243                 onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
244             } catch (InterruptedException e) {
245             }
246             if (onCommitCallback.mLatch.getCount() > 0) {
247                 Log.e(TAG, "Failed to wait for commit callback");
248             }
249         }
250 
setQuadrantBuffer(long surfaceControl, long surfaceTransaction, int width, int height, int colorTopLeft, int colorTopRight, int colorBottomRight, int colorBottomLeft)251         public void setQuadrantBuffer(long surfaceControl, long surfaceTransaction, int width,
252                 int height, int colorTopLeft, int colorTopRight, int colorBottomRight,
253                 int colorBottomLeft) {
254             long buffer = nSurfaceTransaction_setQuadrantBuffer(surfaceControl, surfaceTransaction,
255                     width, height, colorTopLeft, colorTopRight, colorBottomRight, colorBottomLeft);
256             assertTrue("failed to set buffer", buffer != 0);
257             mBuffers.add(buffer);
258         }
259 
setQuadrantBuffer(long surfaceControl, int width, int height, int colorTopLeft, int colorTopRight, int colorBottomRight, int colorBottomLeft)260         public void setQuadrantBuffer(long surfaceControl, int width, int height, int colorTopLeft,
261                 int colorTopRight, int colorBottomRight, int colorBottomLeft) {
262             long surfaceTransaction = createSurfaceTransaction();
263             setQuadrantBuffer(surfaceControl, surfaceTransaction, width, height, colorTopLeft,
264                     colorTopRight, colorBottomRight, colorBottomLeft);
265             TimedTransactionListener onCommitCallback = new TimedTransactionListener();
266             nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
267             applyAndDeleteSurfaceTransaction(surfaceTransaction);
268             try {
269                 onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
270             } catch (InterruptedException e) {
271             }
272             if (onCommitCallback.mLatch.getCount() > 0) {
273                 Log.e(TAG, "Failed to wait for commit callback");
274             }
275         }
276     }
277 
278     ///////////////////////////////////////////////////////////////////////////
279     // Tests
280     ///////////////////////////////////////////////////////////////////////////
281 
verifyTest(BasicSurfaceHolderCallback callback, PixelChecker pixelChecker)282     private void verifyTest(BasicSurfaceHolderCallback callback, PixelChecker pixelChecker) {
283         SurfaceHolderCallback surfaceHolderCallback = new SurfaceHolderCallback(callback);
284         mActivity.verifyTest(surfaceHolderCallback, pixelChecker, mName);
285     }
286 
287     @Test
testSurfaceTransaction_create()288     public void testSurfaceTransaction_create() {
289         long surfaceTransaction = nSurfaceTransaction_create();
290         assertTrue("failed to create surface transaction", surfaceTransaction != 0);
291 
292         nSurfaceTransaction_delete(surfaceTransaction);
293     }
294 
295     @Test
testSurfaceTransaction_apply()296     public void testSurfaceTransaction_apply() {
297         long surfaceTransaction = nSurfaceTransaction_create();
298         assertTrue("failed to create surface transaction", surfaceTransaction != 0);
299 
300         Log.e("Transaction", "created: " + surfaceTransaction);
301 
302         nSurfaceTransaction_apply(surfaceTransaction);
303         nSurfaceTransaction_delete(surfaceTransaction);
304     }
305 
306     // INTRO: The following tests run a series of commands and verify the
307     // output based on the number of pixels with a certain color on the display.
308     //
309     // The interface being tested is a NDK api but the only way to record the display
310     // through public apis is in through the SDK. So the test logic and test verification
311     // is in Java but the hooks that call into the NDK api are jni code.
312     //
313     // The set up is done during the surfaceCreated callback. In most cases, the
314     // test uses the opportunity to create a child layer through createFromWindow and
315     // performs operations on the child layer.
316     //
317     // When there is no visible buffer for the layer(s) the color defaults to black.
318     // The test cases allow a +/- 10% error rate. This is based on the error
319     // rate allowed in the SurfaceViewSyncTests
320 
321     @Test
testSurfaceControl_createFromWindow()322     public void testSurfaceControl_createFromWindow() {
323         verifyTest(
324                 new BasicSurfaceHolderCallback() {
325                     @Override
326                     public void surfaceCreated(SurfaceHolder holder) {
327                         long surfaceControl = createFromWindow(holder.getSurface());
328                     }
329                 },
330                 new PixelChecker(Color.YELLOW) { //10000
331                     @Override
332                     public boolean checkPixels(int pixelCount, int width, int height) {
333                         return pixelCount > 9000 && pixelCount < 11000;
334                     }
335                 });
336     }
337 
338     @Test
testSurfaceControl_create()339     public void testSurfaceControl_create() {
340         verifyTest(
341                 new BasicSurfaceHolderCallback() {
342                     @Override
343                     public void surfaceCreated(SurfaceHolder holder) {
344                         long parentSurfaceControl = createFromWindow(holder.getSurface());
345                         long childSurfaceControl = create(parentSurfaceControl);
346                     }
347                 },
348                 new PixelChecker(Color.YELLOW) { //10000
349                     @Override
350                     public boolean checkPixels(int pixelCount, int width, int height) {
351                         return pixelCount > 9000 && pixelCount < 11000;
352                     }
353                 });
354     }
355 
356     @Test
testSurfaceControl_fromJava()357     public void testSurfaceControl_fromJava() {
358         SurfaceControl.Builder builder = new SurfaceControl.Builder();
359         builder.setName("testSurfaceControl_fromJava");
360         SurfaceControl control = builder.build();
361         final long childSurfaceControl = nSurfaceControl_fromJava(control);
362         assertTrue(childSurfaceControl != 0);
363         verifyTest(
364                 new BasicSurfaceHolderCallback() {
365                     @Override
366                     public void surfaceCreated(SurfaceHolder holder) {
367                         long parentSurfaceControl = createFromWindow(holder.getSurface());
368                         setVisibility(childSurfaceControl, true);
369                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
370                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
371                         reparent(childSurfaceControl, parentSurfaceControl);
372                     }
373                 },
374                 new PixelChecker(Color.RED) { //10000
375                     @Override
376                     public boolean checkPixels(int pixelCount, int width, int height) {
377                         return pixelCount > 9000 && pixelCount < 11000;
378                     }
379                 });
380         nSurfaceControl_release(childSurfaceControl);
381     }
382 
383     @Test
testSurfaceTransaction_fromJava()384     public void testSurfaceTransaction_fromJava() {
385         SurfaceControl.Transaction jTransaction = new SurfaceControl.Transaction();
386         final long transaction = nSurfaceTransaction_fromJava(jTransaction);
387         verifyTest(
388                 new BasicSurfaceHolderCallback() {
389                     @Override
390                     public void surfaceCreated(SurfaceHolder holder) {
391                         long surfaceControl = createFromWindow(holder.getSurface());
392                         setSolidBuffer(surfaceControl, transaction, DEFAULT_LAYOUT_WIDTH,
393                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
394                         nSurfaceTransaction_apply(transaction);
395                     }
396                 },
397                 new PixelChecker(Color.RED) { //10000
398                     @Override
399                     public boolean checkPixels(int pixelCount, int width, int height) {
400                         return pixelCount > 9000 && pixelCount < 11000;
401                     }
402                 });
403         Reference.reachabilityFence(jTransaction);
404     }
405 
406     @Test
testSurfaceControl_acquire()407     public void testSurfaceControl_acquire() {
408         verifyTest(
409                 new BasicSurfaceHolderCallback() {
410                     @Override
411                     public void surfaceCreated(SurfaceHolder holder) {
412                         long surfaceControl = createFromWindow(holder.getSurface());
413                         // increment one refcount
414                         nSurfaceControl_acquire(surfaceControl);
415                         // decrement one refcount incremented from create call
416                         nSurfaceControl_release(surfaceControl);
417                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
418                                 Color.RED);
419                     }
420                 },
421                 new PixelChecker(Color.RED) { //10000
422                     @Override
423                     public boolean checkPixels(int pixelCount, int width, int height) {
424                         return pixelCount > 9000 && pixelCount < 11000;
425                     }
426                 });
427     }
428 
429     @Test
testSurfaceTransaction_setBuffer()430     public void testSurfaceTransaction_setBuffer() {
431         verifyTest(
432                 new BasicSurfaceHolderCallback() {
433                     @Override
434                     public void surfaceCreated(SurfaceHolder holder) {
435                         long surfaceControl = createFromWindow(holder.getSurface());
436                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
437                                 Color.RED);
438                     }
439                 },
440                 new PixelChecker(Color.RED) { //10000
441                     @Override
442                     public boolean checkPixels(int pixelCount, int width, int height) {
443                         return pixelCount > 9000 && pixelCount < 11000;
444                     }
445                 });
446     }
447 
448     @Test
testSurfaceTransaction_setNullBuffer()449     public void testSurfaceTransaction_setNullBuffer() {
450         verifyTest(
451                 new BasicSurfaceHolderCallback() {
452                     @Override
453                     public void surfaceCreated(SurfaceHolder holder) {
454                         long surfaceControl = createFromWindow(holder.getSurface());
455                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
456                                 Color.RED);
457                         setNullBuffer(surfaceControl);
458                     }
459                 },
460                 new PixelChecker(Color.YELLOW) { //10000
461                     @Override
462                     public boolean checkPixels(int pixelCount, int width, int height) {
463                         return pixelCount > 9000 && pixelCount < 11000;
464                     }
465                 });
466     }
467 
468     @Test
testSurfaceTransaction_setBuffer_parentAndChild()469     public void testSurfaceTransaction_setBuffer_parentAndChild() {
470         verifyTest(
471                 new BasicSurfaceHolderCallback() {
472                     @Override
473                     public void surfaceCreated(SurfaceHolder holder) {
474                         long parentSurfaceControl = createFromWindow(holder.getSurface());
475                         long childSurfaceControl = create(parentSurfaceControl);
476 
477                         setSolidBuffer(parentSurfaceControl, DEFAULT_LAYOUT_WIDTH,
478                                 DEFAULT_LAYOUT_HEIGHT, Color.BLUE);
479                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
480                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
481                     }
482                 },
483                 new PixelChecker(Color.RED) { //10000
484                     @Override
485                     public boolean checkPixels(int pixelCount, int width, int height) {
486                         return pixelCount > 9000 && pixelCount < 11000;
487                     }
488                 });
489     }
490 
491     @Test
testSurfaceTransaction_setBuffer_childOnly()492     public void testSurfaceTransaction_setBuffer_childOnly() {
493         verifyTest(
494                 new BasicSurfaceHolderCallback() {
495                     @Override
496                     public void surfaceCreated(SurfaceHolder holder) {
497                         long parentSurfaceControl = createFromWindow(holder.getSurface());
498                         long childSurfaceControl = create(parentSurfaceControl);
499 
500                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
501                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
502                     }
503                 },
504                 new PixelChecker(Color.RED) { //10000
505                     @Override
506                     public boolean checkPixels(int pixelCount, int width, int height) {
507                         return pixelCount > 9000 && pixelCount < 11000;
508                     }
509                 });
510     }
511 
512     @Test
testSurfaceTransaction_setVisibility_show()513     public void testSurfaceTransaction_setVisibility_show() {
514         verifyTest(
515                 new BasicSurfaceHolderCallback() {
516                     @Override
517                     public void surfaceCreated(SurfaceHolder holder) {
518                         long surfaceControl = createFromWindow(holder.getSurface());
519 
520                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
521                                 Color.RED);
522                         setVisibility(surfaceControl, true);
523                     }
524                 },
525                 new PixelChecker(Color.RED) { //10000
526                     @Override
527                     public boolean checkPixels(int pixelCount, int width, int height) {
528                         return pixelCount > 9000 && pixelCount < 11000;
529                     }
530                 });
531     }
532 
533     @Test
testSurfaceTransaction_setVisibility_hide()534     public void testSurfaceTransaction_setVisibility_hide() {
535         verifyTest(
536                 new BasicSurfaceHolderCallback() {
537                     @Override
538                     public void surfaceCreated(SurfaceHolder holder) {
539                         long surfaceControl = createFromWindow(holder.getSurface());
540 
541                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
542                                 Color.RED);
543                         setVisibility(surfaceControl, false);
544                     }
545                 },
546                 new PixelChecker(Color.YELLOW) { //10000
547                     @Override
548                     public boolean checkPixels(int pixelCount, int width, int height) {
549                         return pixelCount > 9000 && pixelCount < 11000;
550                     }
551                 });
552     }
553 
554     @Test
testSurfaceTransaction_setBufferOpaque_opaque()555     public void testSurfaceTransaction_setBufferOpaque_opaque() {
556         verifyTest(
557                 new BasicSurfaceHolderCallback() {
558                     @Override
559                     public void surfaceCreated(SurfaceHolder holder) {
560                         long surfaceControl = createFromWindow(holder.getSurface());
561 
562                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
563                                 PixelColor.TRANSLUCENT_RED);
564                         setBufferOpaque(surfaceControl, true);
565                     }
566                 },
567                 new PixelChecker(Color.RED) { //10000
568                     @Override
569                     public boolean checkPixels(int pixelCount, int width, int height) {
570                         return pixelCount > 9000 && pixelCount < 11000;
571                     }
572                 });
573     }
574 
575     @Test
testSurfaceTransaction_setBufferOpaque_translucent()576     public void testSurfaceTransaction_setBufferOpaque_translucent() {
577         verifyTest(
578                 new BasicSurfaceHolderCallback() {
579                     @Override
580                     public void surfaceCreated(SurfaceHolder holder) {
581                         long surfaceControl = createFromWindow(holder.getSurface());
582 
583                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
584                                 PixelColor.TRANSLUCENT_RED);
585                         setBufferOpaque(surfaceControl, false);
586                     }
587                 },
588                 // setBufferOpaque is an optimization that can be used by SurfaceFlinger.
589                 // It isn't required to affect SurfaceFlinger's behavior.
590                 //
591                 // Ideally we would check for a specific blending of red with a layer below
592                 // it. Unfortunately we don't know what blending the layer will use and
593                 // we don't know what variation the GPU/DPU/blitter might have. Although
594                 // we don't know what shade of red might be present, we can at least check
595                 // that the optimization doesn't cause the framework to drop the buffer entirely.
596                 new PixelChecker(Color.YELLOW, false /* logWhenNoMatch */) {
597                     @Override
598                     public boolean checkPixels(int pixelCount, int width, int height) {
599                         return pixelCount == 0;
600                     }
601                 });
602     }
603 
604     @Test
testSurfaceTransaction_setDestinationRect()605     public void testSurfaceTransaction_setDestinationRect() {
606         verifyTest(
607                 new BasicSurfaceHolderCallback() {
608                     @Override
609                     public void surfaceCreated(SurfaceHolder holder) {
610                         long surfaceControl = createFromWindow(holder.getSurface());
611 
612                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
613                                 Color.RED);
614                     }
615                 },
616                 new PixelChecker(Color.RED) { //10000
617                     @Override
618                     public boolean checkPixels(int pixelCount, int width, int height) {
619                         return pixelCount > 9000 && pixelCount < 11000;
620                     }
621                 });
622     }
623 
624     @Test
testSurfaceTransaction_setDestinationRect_small()625     public void testSurfaceTransaction_setDestinationRect_small() {
626         verifyTest(
627                 new BasicSurfaceHolderCallback() {
628                     @Override
629                     public void surfaceCreated(SurfaceHolder holder) {
630                         long surfaceControl = createFromWindow(holder.getSurface());
631 
632                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
633                                 Color.RED);
634                         setGeometry(surfaceControl, 0, 0, 100, 100, 10, 10, 50, 50, 0);
635                     }
636                 },
637                 new RectChecker(DEFAULT_RECT) {
638                     @Override
639                     public PixelColor getExpectedColor(int x, int y) {
640                         if (x >= 10 && x < 50 && y >= 10 && y < 50) {
641                             return RED;
642                         } else {
643                             return YELLOW;
644                         }
645                     }
646                 });
647     }
648 
649     @Test
testSurfaceTransaction_setDestinationRect_childSmall()650     public void testSurfaceTransaction_setDestinationRect_childSmall() {
651         verifyTest(
652                 new BasicSurfaceHolderCallback() {
653                     @Override
654                     public void surfaceCreated(SurfaceHolder holder) {
655                         long parentSurfaceControl = createFromWindow(holder.getSurface());
656                         long childSurfaceControl = create(parentSurfaceControl);
657 
658                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
659                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
660                         setGeometry(childSurfaceControl, 0, 0, 100, 100, 10, 10, 50, 50, 0);
661                     }
662                 },
663                 new RectChecker(DEFAULT_RECT) {
664                     @Override
665                     public PixelColor getExpectedColor(int x, int y) {
666                         if (x >= 10 && x < 50 && y >= 10 && y < 50) {
667                             return RED;
668                         } else {
669                             return YELLOW;
670                         }
671                     }
672                 });
673     }
674 
675     @Test
testSurfaceTransaction_setDestinationRect_extraLarge()676     public void testSurfaceTransaction_setDestinationRect_extraLarge() {
677         verifyTest(
678                 new BasicSurfaceHolderCallback() {
679                     @Override
680                     public void surfaceCreated(SurfaceHolder holder) {
681                         long surfaceControl = createFromWindow(holder.getSurface());
682 
683                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
684                                 Color.RED);
685                         setGeometry(surfaceControl, 0, 0, 100, 100, -100, -100, 200, 200, 0);
686                     }
687                 },
688                 new PixelChecker(Color.RED) { //10000
689                     @Override
690                     public boolean checkPixels(int pixelCount, int width, int height) {
691                         return pixelCount > 9000 && pixelCount < 11000;
692                     }
693                 });
694     }
695 
696     @Test
testSurfaceTransaction_setDestinationRect_childExtraLarge()697     public void testSurfaceTransaction_setDestinationRect_childExtraLarge() {
698         verifyTest(
699                 new BasicSurfaceHolderCallback() {
700                     @Override
701                     public void surfaceCreated(SurfaceHolder holder) {
702                         long parentSurfaceControl = createFromWindow(holder.getSurface());
703                         long childSurfaceControl = create(parentSurfaceControl);
704 
705                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
706                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
707                         setGeometry(childSurfaceControl, 0, 0, 100, 100, -100, -100, 200, 200, 0);
708                     }
709                 },
710                 new PixelChecker(Color.RED) { //10000
711                     @Override
712                     public boolean checkPixels(int pixelCount, int width, int height) {
713                         return pixelCount > 9000 && pixelCount < 11000;
714                     }
715                 });
716     }
717 
718     @Test
testSurfaceTransaction_setDestinationRect_negativeOffset()719     public void testSurfaceTransaction_setDestinationRect_negativeOffset() {
720         verifyTest(
721                 new BasicSurfaceHolderCallback() {
722                     @Override
723                     public void surfaceCreated(SurfaceHolder holder) {
724                         long surfaceControl = createFromWindow(holder.getSurface());
725 
726                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
727                                 Color.RED);
728                         setGeometry(surfaceControl, 0, 0, 100, 100, -30, -20, 50, 50, 0);
729                     }
730                 },
731                 new RectChecker(DEFAULT_RECT) {
732                     @Override
733                     public PixelColor getExpectedColor(int x, int y) {
734                         if (x < 80 && y < 70) {
735                             return RED;
736                         } else {
737                             return YELLOW;
738                         }
739                     }
740                 });
741     }
742 
743     @Test
testSurfaceTransaction_setDestinationRect_outOfParentBounds()744     public void testSurfaceTransaction_setDestinationRect_outOfParentBounds() {
745         verifyTest(
746                 new BasicSurfaceHolderCallback() {
747                     @Override
748                     public void surfaceCreated(SurfaceHolder holder) {
749                         long surfaceControl = createFromWindow(holder.getSurface());
750 
751                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
752                                 Color.RED);
753                         setGeometry(surfaceControl, 0, 0, 100, 100, 50, 50, 110, 105, 0);
754                     }
755                 },
756                 new RectChecker(DEFAULT_RECT) {
757                     @Override
758                     public PixelColor getExpectedColor(int x, int y) {
759                         if (x >= 50 && y >= 50) {
760                             return RED;
761                         } else {
762                             return YELLOW;
763                         }
764                     }
765                 });
766     }
767 
768     @Test
testSurfaceTransaction_setDestinationRect_twoLayers()769     public void testSurfaceTransaction_setDestinationRect_twoLayers() {
770         verifyTest(
771                 new BasicSurfaceHolderCallback() {
772                     @Override
773                     public void surfaceCreated(SurfaceHolder holder) {
774                         long surfaceControl1 = createFromWindow(holder.getSurface());
775                         long surfaceControl2 = createFromWindow(holder.getSurface());
776 
777                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
778                                 Color.RED);
779                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
780                                 Color.BLUE);
781                         setGeometry(surfaceControl1, 0, 0, 100, 100, 10, 10, 30, 40, 0);
782                         setGeometry(surfaceControl2, 0, 0, 100, 100, 70, 20, 90, 50, 0);
783                     }
784                 },
785                 new RectChecker(DEFAULT_RECT) {
786                     @Override
787                     public PixelColor getExpectedColor(int x, int y) {
788                         if (x >= 10 && x < 30 && y >= 10 && y < 40) {
789                             return RED;
790                         } else if (x >= 70 && x < 90 && y >= 20 && y < 50) {
791                             return BLUE;
792                         } else {
793                             return YELLOW;
794                         }
795                     }
796                 });
797     }
798 
799     @Test
testSurfaceTransaction_setSourceRect()800     public void testSurfaceTransaction_setSourceRect() {
801         verifyTest(
802                 new BasicSurfaceHolderCallback() {
803                     @Override
804                     public void surfaceCreated(SurfaceHolder holder) {
805                         long surfaceControl = createFromWindow(holder.getSurface());
806 
807                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
808                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
809                                 Color.MAGENTA, Color.GREEN);
810                     }
811                 },
812                 new RectChecker(DEFAULT_RECT) {
813                     @Override
814                     public PixelColor getExpectedColor(int x, int y) {
815                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
816                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
817                         if (x < halfWidth && y < halfHeight) {
818                             return RED;
819                         } else if (x >= halfWidth && y < halfHeight) {
820                             return BLUE;
821                         } else if (x < halfWidth && y >= halfHeight) {
822                             return GREEN;
823                         } else {
824                             return MAGENTA;
825                         }
826                     }
827                 });
828     }
829 
830     @Test
testSurfaceTransaction_setSourceRect_smallCentered()831     public void testSurfaceTransaction_setSourceRect_smallCentered() {
832         // These rectangles leave two 10px strips unchecked to allow blended pixels due to GL
833         // texture filtering.
834         Rect topLeft = new Rect(0, 0, 45, 45);
835         Rect topRight = new Rect(55, 0, 100, 45);
836         Rect bottomLeft = new Rect(0, 55, 45, 100);
837         Rect bottomRight = new Rect(55, 55, 100, 100);
838         verifyTest(
839                 new BasicSurfaceHolderCallback() {
840                     @Override
841                     public void surfaceCreated(SurfaceHolder holder) {
842                         long surfaceControl = createFromWindow(holder.getSurface());
843 
844                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
845                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
846                                 Color.MAGENTA, Color.GREEN);
847                         setGeometry(surfaceControl, 10, 10, 90, 90, 0, 0, 100, 100, 0);
848                     }
849                 },
850 
851                 new RectChecker(List.of(topLeft, topRight, bottomLeft, bottomRight)) {
852                     @Override
853                     public PixelColor getExpectedColor(int x, int y) {
854                         if (topLeft.contains(x, y)) {
855                             return RED;
856                         } else if (topRight.contains(x, y)) {
857                             return BLUE;
858                         } else if (bottomLeft.contains(x, y)) {
859                             return GREEN;
860                         } else if (bottomRight.contains(x, y)) {
861                             return MAGENTA;
862                         }
863                         throw new AssertionError(String.format("Unexpected pixel (%d, %d)", x, y));
864                     }
865                 });
866     }
867 
868     @Test
testSurfaceTransaction_setSourceRect_small()869     public void testSurfaceTransaction_setSourceRect_small() {
870         // These rectangles leave a 10px strip unchecked to allow blended pixels due to GL
871         // texture filtering.
872         Rect topHalf = new Rect(0, 0, 100, 45);
873         Rect bottomHalf = new Rect(0, 55, 100, 100);
874         verifyTest(
875                 new BasicSurfaceHolderCallback() {
876                     @Override
877                     public void surfaceCreated(SurfaceHolder holder) {
878                         long surfaceControl = createFromWindow(holder.getSurface());
879 
880                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
881                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
882                                 Color.MAGENTA, Color.GREEN);
883                         setGeometry(surfaceControl, 60, 10, 90, 90, 0, 0, 100, 100, 0);
884                     }
885                 },
886                 new RectChecker(List.of(topHalf, bottomHalf)) {
887                     @Override
888                     public PixelColor getExpectedColor(int x, int y) {
889                         if (topHalf.contains(x, y)) {
890                             return BLUE;
891                         } else if (bottomHalf.contains(x, y)) {
892                             return MAGENTA;
893                         }
894                         throw new AssertionError(String.format("Unexpected pixel (%d, %d)", x, y));
895                     }
896                 });
897     }
898 
899     @Test
testSurfaceTransaction_setSourceRect_extraLarge()900     public void testSurfaceTransaction_setSourceRect_extraLarge() {
901         verifyTest(
902                 new BasicSurfaceHolderCallback() {
903                     @Override
904                     public void surfaceCreated(SurfaceHolder holder) {
905                         long surfaceControl = createFromWindow(holder.getSurface());
906 
907                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
908                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
909                                 Color.MAGENTA, Color.GREEN);
910                         setGeometry(surfaceControl, -50, -50, 150, 150, 0, 0, 100, 100, 0);
911                     }
912                 },
913 
914                 new RectChecker(DEFAULT_RECT) {
915                     @Override
916                     public PixelColor getExpectedColor(int x, int y) {
917                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
918                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
919                         if (x < halfWidth && y < halfHeight) {
920                             return RED;
921                         } else if (x >= halfWidth && y < halfHeight) {
922                             return BLUE;
923                         } else if (x < halfWidth && y >= halfHeight) {
924                             return GREEN;
925                         } else {
926                             return MAGENTA;
927                         }
928                     }
929                 });
930     }
931 
932     @Test
testSurfaceTransaction_setSourceRect_badOffset()933     public void testSurfaceTransaction_setSourceRect_badOffset() {
934         verifyTest(
935                 new BasicSurfaceHolderCallback() {
936                     @Override
937                     public void surfaceCreated(SurfaceHolder holder) {
938                         long surfaceControl = createFromWindow(holder.getSurface());
939 
940                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
941                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
942                                 Color.MAGENTA, Color.GREEN);
943                         setGeometry(surfaceControl, -50, -50, 50, 50, 0, 0, 100, 100, 0);
944                     }
945                 },
946                 new PixelChecker(Color.RED) { //10000
947                     @Override
948                     public boolean checkPixels(int pixelCount, int width, int height) {
949                         return pixelCount > 9000 && pixelCount < 11000;
950                     }
951                 });
952     }
953 
954     @Test
testSurfaceTransaction_setTransform_flipH()955     public void testSurfaceTransaction_setTransform_flipH() {
956         verifyTest(
957                 new BasicSurfaceHolderCallback() {
958                     @Override
959                     public void surfaceCreated(SurfaceHolder holder) {
960                         long surfaceControl = createFromWindow(holder.getSurface());
961 
962                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
963                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
964                                 Color.MAGENTA, Color.GREEN);
965                         setGeometry(surfaceControl, 0, 0, 100, 100, 0, 0, 100, 100,
966                                 /*NATIVE_WINDOW_TRANSFORM_FLIP_H*/ 1);
967                     }
968                 },
969                 new RectChecker(DEFAULT_RECT) {
970                     @Override
971                     public PixelColor getExpectedColor(int x, int y) {
972                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
973                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
974                         if (x < halfWidth && y < halfHeight) {
975                             return BLUE;
976                         } else if (x >= halfWidth && y < halfHeight) {
977                             return RED;
978                         } else if (x < halfWidth && y >= halfHeight) {
979                             return MAGENTA;
980                         } else {
981                             return GREEN;
982                         }
983                     }
984                 });
985     }
986 
987     @Test
testSurfaceTransaction_setTransform_rotate180()988     public void testSurfaceTransaction_setTransform_rotate180() {
989         verifyTest(
990                 new BasicSurfaceHolderCallback() {
991                     @Override
992                     public void surfaceCreated(SurfaceHolder holder) {
993                         long surfaceControl = createFromWindow(holder.getSurface());
994 
995                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
996                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
997                                 Color.MAGENTA, Color.GREEN);
998                         setGeometry(surfaceControl, 0, 0, 100, 100, 0, 0, 100, 100,
999                                 /*NATIVE_WINDOW_TRANSFORM_ROT_180*/ 3);
1000                     }
1001                 },
1002                 new RectChecker(DEFAULT_RECT) {
1003                     @Override
1004                     public PixelColor getExpectedColor(int x, int y) {
1005                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1006                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1007                         if (x < halfWidth && y < halfHeight) {
1008                             return MAGENTA;
1009                         } else if (x >= halfWidth && y < halfHeight) {
1010                             return GREEN;
1011                         } else if (x < halfWidth && y >= halfHeight) {
1012                             return BLUE;
1013                         } else {
1014                             return RED;
1015                         }
1016                     }
1017                 });
1018     }
1019 
1020     @Test
testSurfaceTransaction_setDamageRegion_all()1021     public void testSurfaceTransaction_setDamageRegion_all() {
1022         verifyTest(
1023                 new BasicSurfaceHolderCallback() {
1024                     @Override
1025                     public void surfaceCreated(SurfaceHolder holder) {
1026                         long surfaceControl = createFromWindow(holder.getSurface());
1027                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1028                                 Color.RED);
1029 
1030                         long surfaceTransaction = createSurfaceTransaction();
1031                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
1032                                 DEFAULT_LAYOUT_HEIGHT, Color.BLUE);
1033                         nSurfaceTransaction_setDamageRegion(surfaceControl, surfaceTransaction, 0,
1034                                 0, 100, 100);
1035                         applyAndDeleteSurfaceTransaction(surfaceTransaction);
1036                     }
1037                 },
1038                 new PixelChecker(Color.BLUE) { //10000
1039                     @Override
1040                     public boolean checkPixels(int pixelCount, int width, int height) {
1041                         return pixelCount > 9000 && pixelCount < 11000;
1042                     }
1043                 });
1044     }
1045 
1046     @Test
testSurfaceTransaction_setZOrder_zero()1047     public void testSurfaceTransaction_setZOrder_zero() {
1048         verifyTest(
1049                 new BasicSurfaceHolderCallback() {
1050                     @Override
1051                     public void surfaceCreated(SurfaceHolder holder) {
1052                         long surfaceControl1 = createFromWindow(holder.getSurface());
1053                         long surfaceControl2 = createFromWindow(holder.getSurface());
1054                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1055                                 Color.RED);
1056                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1057                                 Color.MAGENTA);
1058 
1059                         setZOrder(surfaceControl1, 1);
1060                         setZOrder(surfaceControl2, 0);
1061                     }
1062                 },
1063                 new RectChecker(DEFAULT_RECT) {
1064                     @Override
1065                     public PixelColor getExpectedColor(int x, int y) {
1066                         return RED;
1067                     }
1068                 });
1069     }
1070 
1071     @Test
testSurfaceTransaction_setZOrder_positive()1072     public void testSurfaceTransaction_setZOrder_positive() {
1073         verifyTest(
1074                 new BasicSurfaceHolderCallback() {
1075                     @Override
1076                     public void surfaceCreated(SurfaceHolder holder) {
1077                         long surfaceControl1 = createFromWindow(holder.getSurface());
1078                         long surfaceControl2 = createFromWindow(holder.getSurface());
1079                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1080                                 Color.RED);
1081                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1082                                 Color.MAGENTA);
1083 
1084                         setZOrder(surfaceControl1, 1);
1085                         setZOrder(surfaceControl2, 5);
1086                     }
1087                 },
1088                 new RectChecker(DEFAULT_RECT) {
1089                     @Override
1090                     public PixelColor getExpectedColor(int x, int y) {
1091                         return MAGENTA;
1092                     }
1093                 });
1094     }
1095 
1096     @Test
testSurfaceTransaction_setZOrder_negative()1097     public void testSurfaceTransaction_setZOrder_negative() {
1098         verifyTest(
1099                 new BasicSurfaceHolderCallback() {
1100                     @Override
1101                     public void surfaceCreated(SurfaceHolder holder) {
1102                         long surfaceControl1 = createFromWindow(holder.getSurface());
1103                         long surfaceControl2 = createFromWindow(holder.getSurface());
1104                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1105                                 Color.RED);
1106                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1107                                 Color.MAGENTA);
1108 
1109                         setZOrder(surfaceControl1, 1);
1110                         setZOrder(surfaceControl2, -15);
1111                     }
1112                 },
1113                 new RectChecker(DEFAULT_RECT) {
1114                     @Override
1115                     public PixelColor getExpectedColor(int x, int y) {
1116                         return RED;
1117                     }
1118                 });
1119     }
1120 
1121     @Test
testSurfaceTransaction_setZOrder_max()1122     public void testSurfaceTransaction_setZOrder_max() {
1123         verifyTest(
1124                 new BasicSurfaceHolderCallback() {
1125                     @Override
1126                     public void surfaceCreated(SurfaceHolder holder) {
1127                         long surfaceControl1 = createFromWindow(holder.getSurface());
1128                         long surfaceControl2 = createFromWindow(holder.getSurface());
1129                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1130                                 Color.RED);
1131                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1132                                 Color.MAGENTA);
1133 
1134                         setZOrder(surfaceControl1, 1);
1135                         setZOrder(surfaceControl2, Integer.MAX_VALUE);
1136                     }
1137                 },
1138                 new RectChecker(DEFAULT_RECT) {
1139                     @Override
1140                     public PixelColor getExpectedColor(int x, int y) {
1141                         return MAGENTA;
1142                     }
1143                 });
1144     }
1145 
1146     @Test
testSurfaceTransaction_setZOrder_min()1147     public void testSurfaceTransaction_setZOrder_min() {
1148         verifyTest(
1149                 new BasicSurfaceHolderCallback() {
1150                     @Override
1151                     public void surfaceCreated(SurfaceHolder holder) {
1152                         long surfaceControl1 = createFromWindow(holder.getSurface());
1153                         long surfaceControl2 = createFromWindow(holder.getSurface());
1154                         setSolidBuffer(surfaceControl1, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1155                                 Color.RED);
1156                         setSolidBuffer(surfaceControl2, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1157                                 Color.MAGENTA);
1158 
1159                         setZOrder(surfaceControl1, 1);
1160                         setZOrder(surfaceControl2, Integer.MIN_VALUE);
1161                     }
1162                 },
1163                 new RectChecker(DEFAULT_RECT) {
1164                     @Override
1165                     public PixelColor getExpectedColor(int x, int y) {
1166                         return RED;
1167                     }
1168                 });
1169     }
1170 
1171     @Test
testSurfaceTransaction_setOnComplete()1172     public void testSurfaceTransaction_setOnComplete() {
1173         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
1174         verifyTest(
1175                 new BasicSurfaceHolderCallback() {
1176                     @Override
1177                     public void surfaceCreated(SurfaceHolder holder) {
1178                         long surfaceControl = createFromWindow(holder.getSurface());
1179 
1180                         long surfaceTransaction = createSurfaceTransaction();
1181                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
1182                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1183                         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
1184                                 false /* waitForFence */, onCompleteCallback);
1185                         applyAndDeleteSurfaceTransaction(surfaceTransaction);
1186 
1187                         // Wait for callbacks to fire.
1188                         try {
1189                             onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
1190                         } catch (InterruptedException e) {
1191                         }
1192                         if (onCompleteCallback.mLatch.getCount() > 0) {
1193                             Log.e(TAG, "Failed to wait for callback");
1194                         }
1195                     }
1196                 },
1197                 new PixelChecker(Color.RED) { //10000
1198                     @Override
1199                     public boolean checkPixels(int pixelCount, int width, int height) {
1200                         return pixelCount > 9000 && pixelCount < 11000;
1201                     }
1202                 });
1203 
1204         // Validate we got callbacks.
1205         assertEquals(0, onCompleteCallback.mLatch.getCount());
1206         assertTrue(onCompleteCallback.mCallbackTime > 0);
1207     }
1208 
1209     @Test
1210     @RequiresDevice // emulators can't support sync fences
testSurfaceTransaction_setDesiredPresentTime_now()1211     public void testSurfaceTransaction_setDesiredPresentTime_now() {
1212         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
1213         verifyTest(
1214                 new BasicSurfaceHolderCallback() {
1215                     @Override
1216                     public void surfaceCreated(SurfaceHolder holder) {
1217                         long surfaceControl = createFromWindow(holder.getSurface());
1218 
1219                         long surfaceTransaction = createSurfaceTransaction();
1220                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
1221                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1222                         mDesiredPresentTime = nSurfaceTransaction_setDesiredPresentTime(
1223                                 surfaceTransaction, 0);
1224                         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
1225                                 true /* waitForFence */, onCompleteCallback);
1226                         applyAndDeleteSurfaceTransaction(surfaceTransaction);
1227                         // Wait for callbacks to fire.
1228                         try {
1229                             onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
1230                         } catch (InterruptedException e) {
1231                         }
1232                         if (onCompleteCallback.mLatch.getCount() > 0) {
1233                             Log.e(TAG, "Failed to wait for callback");
1234                         }
1235                     }
1236                 },
1237                 new PixelChecker(Color.RED) { //10000
1238                     @Override
1239                     public boolean checkPixels(int pixelCount, int width, int height) {
1240                         return pixelCount > 9000 && pixelCount < 11000;
1241                     }
1242                 });
1243 
1244         assertEquals(0, onCompleteCallback.mLatch.getCount());
1245         assertTrue(onCompleteCallback.mCallbackTime > 0);
1246         assertTrue(onCompleteCallback.mLatchTime > 0);
1247 
1248         assertTrue("transaction was presented too early. presentTime="
1249                         + onCompleteCallback.mPresentTime,
1250                 onCompleteCallback.mPresentTime >= mDesiredPresentTime);
1251     }
1252 
1253     @Test
1254     @RequiresDevice // emulators can't support sync fences
testSurfaceTransaction_setDesiredPresentTime_30ms()1255     public void testSurfaceTransaction_setDesiredPresentTime_30ms() {
1256         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
1257         verifyTest(
1258                 new BasicSurfaceHolderCallback() {
1259                     @Override
1260                     public void surfaceCreated(SurfaceHolder holder) {
1261                         long surfaceControl = createFromWindow(holder.getSurface());
1262 
1263                         long surfaceTransaction = createSurfaceTransaction();
1264                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
1265                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1266                         mDesiredPresentTime = nSurfaceTransaction_setDesiredPresentTime(
1267                                 surfaceTransaction, 30000000);
1268                         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
1269                                 true /* waitForFence */, onCompleteCallback);
1270                         applyAndDeleteSurfaceTransaction(surfaceTransaction);
1271                         // Wait for callbacks to fire.
1272                         try {
1273                             onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
1274                         } catch (InterruptedException e) {
1275                         }
1276                         if (onCompleteCallback.mLatch.getCount() > 0) {
1277                             Log.e(TAG, "Failed to wait for callback");
1278                         }
1279                     }
1280                 },
1281                 new PixelChecker(Color.RED) { //10000
1282                     @Override
1283                     public boolean checkPixels(int pixelCount, int width, int height) {
1284                         return pixelCount > 9000 && pixelCount < 11000;
1285                     }
1286                 });
1287 
1288         assertEquals(0, onCompleteCallback.mLatch.getCount());
1289         assertTrue(onCompleteCallback.mCallbackTime > 0);
1290         assertTrue(onCompleteCallback.mLatchTime > 0);
1291 
1292         assertTrue("transaction was presented too early. presentTime="
1293                         + onCompleteCallback.mPresentTime,
1294                 onCompleteCallback.mPresentTime >= mDesiredPresentTime);
1295     }
1296 
1297     @Test
1298     @RequiresDevice // emulators can't support sync fences
testSurfaceTransaction_setDesiredPresentTime_100ms()1299     public void testSurfaceTransaction_setDesiredPresentTime_100ms() {
1300         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
1301         verifyTest(
1302                 new BasicSurfaceHolderCallback() {
1303                     @Override
1304                     public void surfaceCreated(SurfaceHolder holder) {
1305                         long surfaceControl = createFromWindow(holder.getSurface());
1306 
1307                         long surfaceTransaction = createSurfaceTransaction();
1308                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
1309                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1310                         mDesiredPresentTime = nSurfaceTransaction_setDesiredPresentTime(
1311                                 surfaceTransaction, 100000000);
1312                         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
1313                                 true /* waitForFence */, onCompleteCallback);
1314                         applyAndDeleteSurfaceTransaction(surfaceTransaction);
1315                         // Wait for callbacks to fire.
1316                         try {
1317                             onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
1318                         } catch (InterruptedException e) {
1319                         }
1320                         if (onCompleteCallback.mLatch.getCount() > 0) {
1321                             Log.e(TAG, "Failed to wait for callback");
1322                         }
1323                     }
1324                 },
1325                 new PixelChecker(Color.RED) { //10000
1326                     @Override
1327                     public boolean checkPixels(int pixelCount, int width, int height) {
1328                         return pixelCount > 9000 && pixelCount < 11000;
1329                     }
1330                 });
1331 
1332         assertEquals(0, onCompleteCallback.mLatch.getCount());
1333 
1334         assertTrue(onCompleteCallback.mCallbackTime > 0);
1335         assertTrue(onCompleteCallback.mLatchTime > 0);
1336 
1337         assertTrue("transaction was presented too early. presentTime="
1338                         + onCompleteCallback.mPresentTime,
1339                 onCompleteCallback.mPresentTime >= mDesiredPresentTime);
1340     }
1341 
1342     @Test
testSurfaceTransaction_setBufferAlpha_1_0()1343     public void testSurfaceTransaction_setBufferAlpha_1_0() {
1344         verifyTest(
1345                 new BasicSurfaceHolderCallback() {
1346                     @Override
1347                     public void surfaceCreated(SurfaceHolder holder) {
1348                         long surfaceControl = createFromWindow(holder.getSurface());
1349 
1350                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1351                                 Color.RED);
1352                         setBufferAlpha(surfaceControl, 1.0);
1353                     }
1354                 },
1355                 new PixelChecker(Color.RED) { //10000
1356                     @Override
1357                     public boolean checkPixels(int pixelCount, int width, int height) {
1358                         return pixelCount > 9000 && pixelCount < 11000;
1359                     }
1360                 });
1361     }
1362 
1363     @Test
testSurfaceTransaction_setBufferAlpha_0_5()1364     public void testSurfaceTransaction_setBufferAlpha_0_5() {
1365         BasicSurfaceHolderCallback callback = new BasicSurfaceHolderCallback() {
1366             @Override
1367             public void surfaceCreated(SurfaceHolder holder) {
1368                 long surfaceControl = createFromWindow(holder.getSurface());
1369 
1370                 setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1371                         Color.RED);
1372                 setBufferAlpha(surfaceControl, 0.5);
1373             }
1374         };
1375         verifyTest(callback,
1376                 new PixelChecker(Color.YELLOW, false /* logWhenNoMatch */) {
1377                     @Override
1378                     public boolean checkPixels(int pixelCount, int width, int height) {
1379                         return pixelCount == 0;
1380                     }
1381                 });
1382         verifyTest(callback,
1383                 new PixelChecker(Color.RED, false /* logWhenNoMatch */) {
1384                     @Override
1385                     public boolean checkPixels(int pixelCount, int width, int height) {
1386                         return pixelCount == 0;
1387                     }
1388                 });
1389     }
1390 
1391     @Test
testSurfaceTransaction_setBufferAlpha_0_0()1392     public void testSurfaceTransaction_setBufferAlpha_0_0() {
1393         verifyTest(
1394                 new BasicSurfaceHolderCallback() {
1395                     @Override
1396                     public void surfaceCreated(SurfaceHolder holder) {
1397                         long surfaceControl = createFromWindow(holder.getSurface());
1398 
1399                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1400                                 Color.RED);
1401                         setBufferAlpha(surfaceControl, 0.0);
1402                     }
1403                 },
1404                 new PixelChecker(Color.YELLOW) { //10000
1405                     @Override
1406                     public boolean checkPixels(int pixelCount, int width, int height) {
1407                         return pixelCount > 9000 && pixelCount < 11000;
1408                     }
1409                 });
1410     }
1411 
1412     @Test
testSurfaceTransaction_reparent()1413     public void testSurfaceTransaction_reparent() {
1414         verifyTest(
1415                 new BasicSurfaceHolderCallback() {
1416                     @Override
1417                     public void surfaceCreated(SurfaceHolder holder) {
1418                         long parentSurfaceControl1 = createFromWindow(holder.getSurface());
1419                         long parentSurfaceControl2 = createFromWindow(holder.getSurface());
1420                         long childSurfaceControl = create(parentSurfaceControl1);
1421 
1422                         setGeometry(parentSurfaceControl1, 0, 0, 100, 100, 0, 0, 25, 100, 0);
1423                         setGeometry(parentSurfaceControl2, 0, 0, 100, 100, 25, 0, 100, 100, 0);
1424 
1425                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
1426                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1427 
1428                         reparent(childSurfaceControl, parentSurfaceControl2);
1429                     }
1430                 },
1431                 new RectChecker(DEFAULT_RECT) {
1432                     @Override
1433                     public PixelColor getExpectedColor(int x, int y) {
1434                         if (x >= 25) {
1435                             return RED;
1436                         } else {
1437                             return YELLOW;
1438                         }
1439                     }
1440                 });
1441     }
1442 
1443     @Test
testSurfaceTransaction_reparent_null()1444     public void testSurfaceTransaction_reparent_null() {
1445         verifyTest(
1446                 new BasicSurfaceHolderCallback() {
1447                     @Override
1448                     public void surfaceCreated(SurfaceHolder holder) {
1449                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1450                         long childSurfaceControl = create(parentSurfaceControl);
1451 
1452                         setSolidBuffer(childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
1453                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1454 
1455                         reparent(childSurfaceControl, 0);
1456                     }
1457                 },
1458                 new PixelChecker(Color.YELLOW) { //10000
1459                     @Override
1460                     public boolean checkPixels(int pixelCount, int width, int height) {
1461                         return pixelCount > 9000 && pixelCount < 11000;
1462                     }
1463                 });
1464     }
1465 
1466     @Test
testSurfaceTransaction_setColor()1467     public void testSurfaceTransaction_setColor() {
1468         verifyTest(
1469                 new BasicSurfaceHolderCallback() {
1470                     @Override
1471                     public void surfaceCreated(SurfaceHolder holder) {
1472                         long surfaceControl = createFromWindow(holder.getSurface());
1473 
1474                         setColor(surfaceControl, 0, 1.0f, 0, 1.0f);
1475                     }
1476                 },
1477                 new PixelChecker(Color.GREEN) { // 10000
1478                     @Override
1479                     public boolean checkPixels(int pixelCount, int width, int height) {
1480                         return pixelCount > 9000 && pixelCount < 11000;
1481                     }
1482                 });
1483     }
1484 
1485     @Test
testSurfaceTransaction_noColorNoBuffer()1486     public void testSurfaceTransaction_noColorNoBuffer() {
1487         verifyTest(
1488                 new BasicSurfaceHolderCallback() {
1489                     @Override
1490                     public void surfaceCreated(SurfaceHolder holder) {
1491                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1492                         long childSurfaceControl = create(parentSurfaceControl);
1493 
1494                         setColor(parentSurfaceControl, 0, 1.0f, 0, 1.0f);
1495                     }
1496                 },
1497                 new PixelChecker(Color.GREEN) { // 10000
1498                     @Override
1499                     public boolean checkPixels(int pixelCount, int width, int height) {
1500                         return pixelCount > 9000 && pixelCount < 11000;
1501                     }
1502                 });
1503     }
1504 
1505     @Test
testSurfaceTransaction_setColorAlpha()1506     public void testSurfaceTransaction_setColorAlpha() {
1507         verifyTest(
1508                 new BasicSurfaceHolderCallback() {
1509                     @Override
1510                     public void surfaceCreated(SurfaceHolder holder) {
1511                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1512                         setColor(parentSurfaceControl, 0, 0, 1.0f, 0);
1513                     }
1514                 },
1515                 new PixelChecker(Color.YELLOW) { // 10000
1516                     @Override
1517                     public boolean checkPixels(int pixelCount, int width, int height) {
1518                         return pixelCount > 9000 && pixelCount < 11000;
1519                     }
1520                 });
1521     }
1522 
1523     @Test
testSurfaceTransaction_setColorAndBuffer()1524     public void testSurfaceTransaction_setColorAndBuffer() {
1525         verifyTest(
1526                 new BasicSurfaceHolderCallback() {
1527                     @Override
1528                     public void surfaceCreated(SurfaceHolder holder) {
1529                         long surfaceControl = createFromWindow(holder.getSurface());
1530 
1531                         setSolidBuffer(
1532                                 surfaceControl, DEFAULT_LAYOUT_WIDTH,
1533                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1534                         setColor(surfaceControl, 0, 1.0f, 0, 1.0f);
1535                     }
1536                 },
1537                 new PixelChecker(Color.RED) { // 10000
1538                     @Override
1539                     public boolean checkPixels(int pixelCount, int width, int height) {
1540                         return pixelCount > 9000 && pixelCount < 11000;
1541                     }
1542                 });
1543     }
1544 
1545     @Test
testSurfaceTransaction_setColorAndBuffer_bufferAlpha_0_5()1546     public void testSurfaceTransaction_setColorAndBuffer_bufferAlpha_0_5() {
1547         verifyTest(
1548                 new BasicSurfaceHolderCallback() {
1549                     @Override
1550                     public void surfaceCreated(SurfaceHolder holder) {
1551                         long surfaceControl = createFromWindow(holder.getSurface());
1552 
1553                         setSolidBuffer(
1554                                 surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1555                                 Color.RED);
1556                         setBufferAlpha(surfaceControl, 0.5);
1557                         setColor(surfaceControl, 0, 0, 1.0f, 1.0f);
1558                     }
1559                 },
1560                 new PixelChecker(Color.RED, false /* logWhenNoMatch */) {
1561                     @Override
1562                     public boolean checkPixels(int pixelCount, int width, int height) {
1563                         return pixelCount == 0;
1564                     }
1565                 });
1566     }
1567 
1568     @Test
testSurfaceTransaction_setBufferNoColor_bufferAlpha_0()1569     public void testSurfaceTransaction_setBufferNoColor_bufferAlpha_0() {
1570         verifyTest(
1571                 new BasicSurfaceHolderCallback() {
1572                     @Override
1573                     public void surfaceCreated(SurfaceHolder holder) {
1574                         long surfaceControlA = createFromWindow(holder.getSurface());
1575                         long surfaceControlB = createFromWindow(holder.getSurface());
1576 
1577                         setColor(surfaceControlA, 1.0f, 0, 0, 1.0f);
1578                         setSolidBuffer(surfaceControlB, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1579                                 Color.TRANSPARENT);
1580 
1581                         setZOrder(surfaceControlA, 1);
1582                         setZOrder(surfaceControlB, 2);
1583                     }
1584                 },
1585                 new PixelChecker(Color.RED) { // 10000
1586                     @Override
1587                     public boolean checkPixels(int pixelCount, int width, int height) {
1588                         return pixelCount > 9000 && pixelCount < 11000;
1589                     }
1590                 });
1591     }
1592 
1593     @Test
testSurfaceTransaction_setColorAndBuffer_hide()1594     public void testSurfaceTransaction_setColorAndBuffer_hide() {
1595         verifyTest(
1596                 new BasicSurfaceHolderCallback() {
1597                     @Override
1598                     public void surfaceCreated(SurfaceHolder holder) {
1599                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1600                         long childSurfaceControl = create(parentSurfaceControl);
1601 
1602                         setColor(parentSurfaceControl, 0, 1.0f, 0, 1.0f);
1603 
1604                         setSolidBuffer(
1605                                 childSurfaceControl, DEFAULT_LAYOUT_WIDTH,
1606                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
1607                         setColor(childSurfaceControl, 0, 0, 1.0f, 1.0f);
1608                         setVisibility(childSurfaceControl, false);
1609                     }
1610                 },
1611                 new PixelChecker(Color.GREEN) { // 10000
1612                     @Override
1613                     public boolean checkPixels(int pixelCount, int width, int height) {
1614                         return pixelCount > 9000 && pixelCount < 11000;
1615                     }
1616                 });
1617     }
1618 
1619     @Test
testSurfaceTransaction_zOrderMultipleSurfaces()1620     public void testSurfaceTransaction_zOrderMultipleSurfaces() {
1621         verifyTest(
1622                 new BasicSurfaceHolderCallback() {
1623                     @Override
1624                     public void surfaceCreated(SurfaceHolder holder) {
1625                         long surfaceControlA = createFromWindow(holder.getSurface());
1626                         long surfaceControlB = createFromWindow(holder.getSurface());
1627 
1628                         // blue color layer of A is above the green buffer and red color layer
1629                         // of B
1630                         setColor(surfaceControlA, 0, 0, 1.0f, 1.0f);
1631                         setSolidBuffer(
1632                                 surfaceControlB, DEFAULT_LAYOUT_WIDTH,
1633                                 DEFAULT_LAYOUT_HEIGHT, Color.GREEN);
1634                         setColor(surfaceControlB, 1.0f, 0, 0, 1.0f);
1635                         setZOrder(surfaceControlA, 5);
1636                         setZOrder(surfaceControlB, 4);
1637                     }
1638                 },
1639                 new PixelChecker(Color.BLUE) { // 10000
1640                     @Override
1641                     public boolean checkPixels(int pixelCount, int width, int height) {
1642                         return pixelCount > 9000 && pixelCount < 11000;
1643                     }
1644                 });
1645     }
1646 
1647     @Test
testSurfaceTransaction_zOrderMultipleSurfacesWithParent()1648     public void testSurfaceTransaction_zOrderMultipleSurfacesWithParent() {
1649         verifyTest(
1650                 new BasicSurfaceHolderCallback() {
1651                     @Override
1652                     public void surfaceCreated(SurfaceHolder holder) {
1653                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1654                         long surfaceControlA = create(parentSurfaceControl);
1655                         long surfaceControlB = create(parentSurfaceControl);
1656 
1657                         setColor(surfaceControlA, 0, 1.0f, 0, 1.0f);
1658                         setSolidBuffer(
1659                                 surfaceControlA, DEFAULT_LAYOUT_WIDTH,
1660                                 DEFAULT_LAYOUT_HEIGHT, Color.GREEN);
1661                         setColor(surfaceControlB, 1.0f, 0, 0, 1.0f);
1662                         setZOrder(surfaceControlA, 3);
1663                         setZOrder(surfaceControlB, 4);
1664                     }
1665                 },
1666                 new PixelChecker(Color.RED) { // 10000
1667                     @Override
1668                     public boolean checkPixels(int pixelCount, int width, int height) {
1669                         return pixelCount > 9000 && pixelCount < 11000;
1670                     }
1671                 });
1672     }
1673 
1674     @Test
testSurfaceTransaction_setPosition()1675     public void testSurfaceTransaction_setPosition() {
1676         verifyTest(
1677                 new BasicSurfaceHolderCallback() {
1678                     @Override
1679                     public void surfaceCreated(SurfaceHolder holder) {
1680                         long surfaceControl = createFromWindow(holder.getSurface());
1681 
1682                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1683                                 Color.RED);
1684                         setPosition(surfaceControl, 20, 10);
1685                     }
1686                 },
1687                 new RectChecker(DEFAULT_RECT) {
1688                     @Override
1689                     public PixelColor getExpectedColor(int x, int y) {
1690                         if (x >= 20 && y >= 10) {
1691                             return RED;
1692                         } else {
1693                             return YELLOW;
1694                         }
1695                     }
1696                 });
1697     }
1698 
1699     @Test
testSurfaceTransaction_setPositionNegative()1700     public void testSurfaceTransaction_setPositionNegative() {
1701         verifyTest(
1702                 new BasicSurfaceHolderCallback() {
1703                     @Override
1704                     public void surfaceCreated(SurfaceHolder holder) {
1705                         long surfaceControl = createFromWindow(holder.getSurface());
1706 
1707                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1708                                 Color.RED);
1709                         // Offset -20, -10
1710                         setPosition(surfaceControl, -20, -10);
1711                     }
1712                 },
1713                 new RectChecker(DEFAULT_RECT) {
1714                     @Override
1715                     public PixelColor getExpectedColor(int x, int y) {
1716                         if (x < DEFAULT_LAYOUT_WIDTH - 20 && y < DEFAULT_LAYOUT_HEIGHT - 10) {
1717                             return RED;
1718                         } else {
1719                             return YELLOW;
1720                         }
1721                     }
1722                 });
1723     }
1724 
1725     @Test
testSurfaceTransaction_setScale()1726     public void testSurfaceTransaction_setScale() {
1727         verifyTest(
1728                 new BasicSurfaceHolderCallback() {
1729                     @Override
1730                     public void surfaceCreated(SurfaceHolder holder) {
1731                         long surfaceControl = createFromWindow(holder.getSurface());
1732 
1733                         setSolidBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
1734                                 Color.RED);
1735                         setScale(surfaceControl, .5f, .5f);
1736                     }
1737                 },
1738                 new RectChecker(DEFAULT_RECT) {
1739                     @Override
1740                     public PixelColor getExpectedColor(int x, int y) {
1741                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1742                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1743                         if (x < halfWidth && y < halfHeight) {
1744                             return RED;
1745                         } else {
1746                             return YELLOW;
1747                         }
1748                     }
1749                 });
1750     }
1751 
1752     @Test
testSurfaceTransaction_scaleToZero()1753     public void testSurfaceTransaction_scaleToZero() {
1754         verifyTest(
1755                 new BasicSurfaceHolderCallback() {
1756                     @Override
1757                     public void surfaceCreated(SurfaceHolder holder) {
1758                         long parentSurfaceControl = createFromWindow(holder.getSurface());
1759                         long childSurfaceControl = create(parentSurfaceControl);
1760 
1761                         setSolidBuffer(parentSurfaceControl,
1762                                 DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, Color.YELLOW);
1763                         setSolidBuffer(childSurfaceControl,
1764                                 DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, Color.RED);
1765                         setScale(childSurfaceControl, 0f, 0f);
1766                     }
1767                 },
1768                 new PixelChecker(Color.YELLOW) {
1769                     @Override
1770                     public boolean checkPixels(int matchingPixelCount, int width, int height) {
1771                         return matchingPixelCount > 9000 & matchingPixelCount < 11000;
1772                     }
1773                 });
1774     }
1775 
1776     @Test
testSurfaceTransaction_setPositionAndScale()1777     public void testSurfaceTransaction_setPositionAndScale() {
1778         verifyTest(
1779                 new BasicSurfaceHolderCallback() {
1780                     @Override
1781                     public void surfaceCreated(SurfaceHolder holder) {
1782                         long surfaceControl = createFromWindow(holder.getSurface());
1783 
1784                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1785                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1786                                 Color.MAGENTA, Color.GREEN);
1787 
1788                         // Set the position to -50, -50 in parent space then scale 2x in each
1789                         // direction relative to 0,0. The end result should be a -50,-50,150,150
1790                         // buffer coverage or essentially a 2x center-scale
1791 
1792                         setPosition(surfaceControl, -50, -50);
1793                         setScale(surfaceControl, 2, 2);
1794                     }
1795                 },
1796                 new RectChecker(new Rect(0, 0, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT)) {
1797                     @Override
1798                     public PixelColor getExpectedColor(int x, int y) {
1799                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1800                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1801                         if (x < halfWidth && y < halfHeight) {
1802                             return RED;
1803                         } else if (x >= halfWidth && y < halfHeight) {
1804                             return BLUE;
1805                         } else if (x < halfWidth && y >= halfHeight) {
1806                             return GREEN;
1807                         } else {
1808                             return MAGENTA;
1809                         }
1810                     }
1811 
1812                     @Override
1813                     public boolean checkPixels(int matchingPixelCount, int width, int height) {
1814                         // There will be sampling artifacts along the center line, ignore those
1815                         return matchingPixelCount > 9000 && matchingPixelCount < 11000;
1816                     }
1817                 });
1818     }
1819 
1820     @Test
testSurfaceTransaction_setBufferTransform90()1821     public void testSurfaceTransaction_setBufferTransform90() {
1822         verifyTest(
1823                 new BasicSurfaceHolderCallback() {
1824                     @Override
1825                     public void surfaceCreated(SurfaceHolder holder) {
1826                         long surfaceControl = createFromWindow(holder.getSurface());
1827 
1828                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1829                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1830                                 Color.MAGENTA, Color.GREEN);
1831                         setPosition(surfaceControl, -50, -50);
1832                         setBufferTransform(surfaceControl, /* NATIVE_WINDOW_TRANSFORM_ROT_90 */ 4);
1833                     }
1834                 },
1835                 new RectChecker(DEFAULT_RECT) {
1836                     @Override
1837                     public PixelColor getExpectedColor(int x, int y) {
1838                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1839                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1840                         if (x < halfWidth && y < halfHeight) {
1841                             return BLUE;
1842                         } else {
1843                             return YELLOW;
1844                         }
1845                     }
1846                 });
1847     }
1848 
1849     @Test
testSurfaceTransaction_setCropSmall()1850     public void testSurfaceTransaction_setCropSmall() {
1851         verifyTest(
1852                 new BasicSurfaceHolderCallback() {
1853                     @Override
1854                     public void surfaceCreated(SurfaceHolder holder) {
1855                         long surfaceControl = createFromWindow(holder.getSurface());
1856 
1857                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1858                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1859                                 Color.MAGENTA, Color.GREEN);
1860                         setCrop(surfaceControl, new Rect(0, 0, 50, 50));
1861                     }
1862                 },
1863 
1864                 new RectChecker(DEFAULT_RECT) {
1865                     @Override
1866                     public PixelColor getExpectedColor(int x, int y) {
1867                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1868                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1869                         if (x < halfWidth && y < halfHeight) {
1870                             return RED;
1871                         } else {
1872                             return YELLOW;
1873                         }
1874                     }
1875                 });
1876     }
1877 
1878     @Test
testSurfaceTransaction_setCropLarge()1879     public void testSurfaceTransaction_setCropLarge() {
1880         verifyTest(
1881                 new BasicSurfaceHolderCallback() {
1882                     @Override
1883                     public void surfaceCreated(SurfaceHolder holder) {
1884                         long surfaceControl = createFromWindow(holder.getSurface());
1885 
1886                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1887                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1888                                 Color.MAGENTA, Color.GREEN);
1889                         setCrop(surfaceControl, new Rect(0, 0, 150, 150));
1890                     }
1891                 },
1892 
1893                 new RectChecker(DEFAULT_RECT) {
1894                     @Override
1895                     public PixelColor getExpectedColor(int x, int y) {
1896                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1897                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1898                         if (x < halfWidth && y < halfHeight) {
1899                             return RED;
1900                         } else if (x >= halfWidth && y < halfHeight) {
1901                             return BLUE;
1902                         } else if (x < halfWidth && y >= halfHeight) {
1903                             return GREEN;
1904                         } else {
1905                             return MAGENTA;
1906                         }
1907                     }
1908                 });
1909     }
1910 
1911     @Test
testSurfaceTransaction_setCropOffset()1912     public void testSurfaceTransaction_setCropOffset() {
1913         verifyTest(
1914                 new BasicSurfaceHolderCallback() {
1915                     @Override
1916                     public void surfaceCreated(SurfaceHolder holder) {
1917                         long surfaceControl = createFromWindow(holder.getSurface());
1918 
1919                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1920                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1921                                 Color.MAGENTA, Color.GREEN);
1922                         setCrop(surfaceControl, new Rect(50, 50, 100, 100));
1923                     }
1924                 }, new RectChecker(DEFAULT_RECT) {
1925                     @Override
1926                     public PixelColor getExpectedColor(int x, int y) {
1927                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1928                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1929                         // Only Magenta is visible in the lower right quadrant
1930                         if (x >= halfWidth && y >= halfHeight) {
1931                             return MAGENTA;
1932                         } else {
1933                             return YELLOW;
1934                         }
1935                     }
1936                 });
1937     }
1938 
1939     @Test
testSurfaceTransaction_setCropNegative()1940     public void testSurfaceTransaction_setCropNegative() {
1941         verifyTest(
1942                 new BasicSurfaceHolderCallback() {
1943                     @Override
1944                     public void surfaceCreated(SurfaceHolder holder) {
1945                         long surfaceControl = createFromWindow(holder.getSurface());
1946 
1947                         setQuadrantBuffer(surfaceControl, DEFAULT_LAYOUT_WIDTH,
1948                                 DEFAULT_LAYOUT_HEIGHT, Color.RED, Color.BLUE,
1949                                 Color.MAGENTA, Color.GREEN);
1950                         setCrop(surfaceControl, new Rect(-50, -50, 50, 50));
1951                     }
1952                 }, new RectChecker(DEFAULT_RECT) {
1953                     @Override
1954                     public PixelColor getExpectedColor(int x, int y) {
1955                         int halfWidth = DEFAULT_LAYOUT_WIDTH / 2;
1956                         int halfHeight = DEFAULT_LAYOUT_HEIGHT / 2;
1957                         if (x < halfWidth && y < halfHeight) {
1958                             return RED;
1959                         } else {
1960                             return YELLOW;
1961                         }
1962                     }
1963                 });
1964     }
1965 
1966     // Returns success of the surface transaction to decide whether to continue the test, such as
1967     // additional assertions.
verifySetFrameTimeline(boolean usePreferredIndex, SurfaceHolder holder)1968     private boolean verifySetFrameTimeline(boolean usePreferredIndex, SurfaceHolder holder) {
1969         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
1970         long surfaceControl = nSurfaceControl_createFromWindow(holder.getSurface());
1971         assertTrue("failed to create surface control", surfaceControl != 0);
1972         long surfaceTransaction = createSurfaceTransaction();
1973         long buffer = nSurfaceTransaction_setSolidBuffer(surfaceControl, surfaceTransaction,
1974                 DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, Color.RED);
1975         assertTrue("failed to set buffer", buffer != 0);
1976 
1977         // Get choreographer frame timelines.
1978         FrameCallbackData frameCallbackData = nGetFrameTimelines();
1979         FrameTimeline[] frameTimelines = frameCallbackData.getFrameTimelines();
1980 
1981         int timelineIndex = frameCallbackData.getPreferredFrameTimelineIndex();
1982         if (!usePreferredIndex) {
1983             if (frameTimelines.length == 1) {
1984                 // If there is only one frame timeline then it is already the preferred timeline.
1985                 // Thus testing a non-preferred index is impossible.
1986                 Log.i(TAG, "Non-preferred frame timeline does not exist");
1987                 return false;
1988             }
1989             if (timelineIndex == frameTimelines.length - 1) {
1990                 timelineIndex--;
1991             } else {
1992                 timelineIndex++;
1993             }
1994         }
1995         FrameTimeline frameTimeline = frameTimelines[timelineIndex];
1996         long vsyncId = frameTimeline.getVsyncId();
1997         assertTrue("Vsync ID not valid", vsyncId > 0);
1998 
1999         Trace.beginSection("Surface transaction created " + vsyncId);
2000         nSurfaceTransaction_setFrameTimeline(surfaceTransaction, vsyncId);
2001         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
2002                 true /* waitForFence */, onCompleteCallback);
2003         applyAndDeleteSurfaceTransaction(surfaceTransaction);
2004         Trace.endSection();
2005 
2006         Trace.beginSection("Wait for complete callback " + vsyncId);
2007         // Wait for callbacks to fire.
2008         try {
2009             onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
2010         } catch (InterruptedException e) {
2011         }
2012         if (onCompleteCallback.mLatch.getCount() > 0) {
2013             Log.e(TAG, "Failed to wait for callback");
2014         }
2015         Trace.endSection();
2016 
2017         assertEquals(0, onCompleteCallback.mLatch.getCount());
2018         assertTrue(onCompleteCallback.mCallbackTime > 0);
2019         assertTrue(onCompleteCallback.mLatchTime > 0);
2020 
2021         long periodNanos = (long) (1e9 / mActivity.getDisplay().getRefreshRate());
2022         long threshold = periodNanos / 2;
2023         // Check that the frame did not present earlier than the frame timeline chosen from setting
2024         // a vsyncId in the surface transaction; this should be guaranteed as part of the API
2025         // specification. Don't check whether the frame presents on-time since it can be flaky from
2026         // other delays.
2027         assertTrue("Frame presented too early using frame timeline index=" + timelineIndex
2028                         + " (preferred index=" + frameCallbackData.getPreferredFrameTimelineIndex()
2029                         + ", preferred vsyncId="
2030                         + frameTimelines[frameCallbackData.getPreferredFrameTimelineIndex()]
2031                                   .getVsyncId()
2032                         + "), vsyncId=" + frameTimeline.getVsyncId() + ", actual presentation time="
2033                         + onCompleteCallback.mPresentTime + ", expected presentation time="
2034                         + frameTimeline.getExpectedPresentTime() + ", actual - expected diff (ns)="
2035                         + (onCompleteCallback.mPresentTime - frameTimeline.getExpectedPresentTime())
2036                         + ", acceptable diff threshold (ns)= " + threshold,
2037                 onCompleteCallback.mPresentTime
2038                         > frameTimeline.getExpectedPresentTime() - threshold);
2039         return true;
2040     }
2041 
2042     @Test
2043     @RequiresDevice // emulators can't support sync fences
testSurfaceTransaction_setFrameTimeline_preferredIndex()2044     public void testSurfaceTransaction_setFrameTimeline_preferredIndex() {
2045         Trace.beginSection(
2046                 "testSurfaceTransaction_setFrameTimeline_preferredIndex");
2047         Trace.endSection();
2048 
2049         BasicSurfaceHolderCallback basicSurfaceHolderCallback = new BasicSurfaceHolderCallback() {
2050             @Override
2051             public void surfaceCreated(SurfaceHolder surfaceHolder) {
2052                 // Noop.
2053             }
2054         };
2055         final CountDownLatch readyFence = new CountDownLatch(1);
2056         ASurfaceControlTestActivity.SurfaceHolderCallback surfaceHolderCallback =
2057                 new ASurfaceControlTestActivity.SurfaceHolderCallback(
2058                         new SurfaceHolderCallback(basicSurfaceHolderCallback), readyFence,
2059                         mActivity.getParentFrameLayout().getRootSurfaceControl());
2060         mActivity.createSurface(surfaceHolderCallback);
2061         try {
2062             assertTrue("timeout", readyFence.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
2063         } catch (InterruptedException e) {
2064             Assert.fail("interrupted");
2065         }
2066         if (!verifySetFrameTimeline(true, mActivity.getSurfaceView().getHolder())) return;
2067         mActivity.verifyScreenshot(
2068                 new PixelChecker(Color.RED) { //10000
2069                     @Override
2070                     public boolean checkPixels(int pixelCount, int width, int height) {
2071                         return pixelCount > 9000 && pixelCount < 11000;
2072                     }
2073                 }, mName);
2074 
2075     }
2076 
2077     @Test
2078     @RequiresDevice // emulators can't support sync fences
testSurfaceTransaction_setFrameTimeline_notPreferredIndex()2079     public void testSurfaceTransaction_setFrameTimeline_notPreferredIndex() {
2080         Trace.beginSection(
2081                 "testSurfaceTransaction_setFrameTimeline_notPreferredIndex");
2082         Trace.endSection();
2083 
2084         BasicSurfaceHolderCallback basicSurfaceHolderCallback = new BasicSurfaceHolderCallback() {
2085             @Override
2086             public void surfaceCreated(SurfaceHolder surfaceHolder) {
2087                 // Noop.
2088             }
2089         };
2090         final CountDownLatch readyFence = new CountDownLatch(1);
2091         ASurfaceControlTestActivity.SurfaceHolderCallback surfaceHolderCallback =
2092                 new ASurfaceControlTestActivity.SurfaceHolderCallback(
2093                         new SurfaceHolderCallback(basicSurfaceHolderCallback), readyFence,
2094                         mActivity.getParentFrameLayout().getRootSurfaceControl());
2095         mActivity.createSurface(surfaceHolderCallback);
2096         try {
2097             assertTrue("timeout", readyFence.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
2098         } catch (InterruptedException e) {
2099             Assert.fail("interrupted");
2100         }
2101         if (!verifySetFrameTimeline(false, mActivity.getSurfaceView().getHolder())) return;
2102         mActivity.verifyScreenshot(
2103                 new PixelChecker(Color.RED) { //10000
2104                     @Override
2105                     public boolean checkPixels(int pixelCount, int width, int height) {
2106                         return pixelCount > 9000 && pixelCount < 11000;
2107                     }
2108                 }, mName);
2109 
2110     }
2111 
2112     static class TimedTransactionListener implements
2113             ASurfaceControlTestUtils.TransactionCompleteListener {
2114         long mCallbackTime = -1;
2115         long mLatchTime = -1;
2116         long mPresentTime = -1;
2117         CountDownLatch mLatch = new CountDownLatch(1);
2118 
2119         @Override
onTransactionComplete(long inLatchTime, long presentTime)2120         public void onTransactionComplete(long inLatchTime, long presentTime) {
2121             mCallbackTime = SystemClock.elapsedRealtime();
2122             mLatchTime = inLatchTime;
2123             mPresentTime = presentTime;
2124             mLatch.countDown();
2125         }
2126     }
2127 
2128     @Test
testSurfaceTransactionOnCommitCallback_emptyTransaction()2129     public void testSurfaceTransactionOnCommitCallback_emptyTransaction()
2130             throws InterruptedException {
2131         // Create and send an empty transaction with onCommit and onComplete callbacks.
2132         long surfaceTransaction = nSurfaceTransaction_create();
2133         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
2134         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction, false /* waitForFence */,
2135                 onCompleteCallback);
2136         TimedTransactionListener onCommitCallback = new TimedTransactionListener();
2137         nSurfaceTransaction_setOnCommitCallback(surfaceTransaction, onCommitCallback);
2138         nSurfaceTransaction_apply(surfaceTransaction);
2139         nSurfaceTransaction_delete(surfaceTransaction);
2140 
2141         // Wait for callbacks to fire.
2142         onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
2143         onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
2144 
2145         // Validate we got callbacks.
2146         assertEquals(0, onCommitCallback.mLatch.getCount());
2147         assertTrue(onCommitCallback.mCallbackTime > 0);
2148         assertEquals(0, onCompleteCallback.mLatch.getCount());
2149         assertTrue(onCompleteCallback.mCallbackTime > 0);
2150 
2151         // Validate we received the callbacks in expected order.
2152         assertTrue(onCommitCallback.mCallbackTime <= onCompleteCallback.mCallbackTime);
2153     }
2154 
2155     @Test
testSurfaceTransactionOnCommitCallback_bufferTransaction()2156     public void testSurfaceTransactionOnCommitCallback_bufferTransaction()
2157             throws Throwable {
2158         // Create and send a transaction with a buffer update and with onCommit and onComplete
2159         // callbacks.
2160         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
2161         TimedTransactionListener onCommitCallback = new TimedTransactionListener();
2162         verifyTest(
2163                 new BasicSurfaceHolderCallback() {
2164                     @Override
2165                     public void surfaceCreated(SurfaceHolder holder) {
2166                         long surfaceTransaction = nSurfaceTransaction_create();
2167                         long surfaceControl = createFromWindow(holder.getSurface());
2168                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
2169                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
2170                         nSurfaceTransaction_setOnCompleteCallback(
2171                                 surfaceTransaction /* waitForFence */, false,
2172                                 onCompleteCallback);
2173                         nSurfaceTransaction_setOnCommitCallback(surfaceTransaction,
2174                                 onCommitCallback);
2175                         nSurfaceTransaction_apply(surfaceTransaction);
2176                         nSurfaceTransaction_delete(surfaceTransaction);
2177 
2178                         // Wait for callbacks to fire.
2179                         try {
2180                             onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
2181                         } catch (InterruptedException e) {
2182                         }
2183                         if (onCommitCallback.mLatch.getCount() > 0) {
2184                             Log.e(TAG, "Failed to wait for commit callback");
2185                         }
2186                     }
2187                 },
2188                 new PixelChecker(Color.RED) { //10000
2189                     @Override
2190                     public boolean checkPixels(int pixelCount, int width, int height) {
2191                         return pixelCount > 9000 && pixelCount < 11000;
2192                     }
2193                 });
2194 
2195         onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
2196 
2197         // Validate we got callbacks with a valid latch time.
2198         assertEquals(0, onCommitCallback.mLatch.getCount());
2199         assertTrue(onCommitCallback.mCallbackTime > 0);
2200         assertTrue(onCommitCallback.mLatchTime > 0);
2201         assertEquals(0, onCompleteCallback.mLatch.getCount());
2202         assertTrue(onCompleteCallback.mCallbackTime > 0);
2203         assertTrue(onCompleteCallback.mLatchTime > 0);
2204 
2205         // Validate we received the callbacks in expected order and the latch times reported
2206         // matches.
2207         assertTrue(onCommitCallback.mCallbackTime <= onCompleteCallback.mCallbackTime);
2208         assertEquals(onCommitCallback.mLatchTime, onCompleteCallback.mLatchTime);
2209     }
2210 
2211     @Test
testSurfaceTransactionOnCommitCallback_geometryTransaction()2212     public void testSurfaceTransactionOnCommitCallback_geometryTransaction()
2213             throws Throwable {
2214         // Create and send a transaction with a buffer update and with onCommit and onComplete
2215         // callbacks.
2216         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
2217         TimedTransactionListener onCommitCallback = new TimedTransactionListener();
2218         verifyTest(
2219                 new BasicSurfaceHolderCallback() {
2220                     @Override
2221                     public void surfaceCreated(SurfaceHolder holder) {
2222                         long surfaceTransaction = nSurfaceTransaction_create();
2223                         long surfaceControl = createFromWindow(holder.getSurface());
2224                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
2225                                 DEFAULT_LAYOUT_HEIGHT, Color.RED);
2226                         nSurfaceTransaction_apply(surfaceTransaction);
2227                         nSurfaceTransaction_delete(surfaceTransaction);
2228                         surfaceTransaction = nSurfaceTransaction_create();
2229                         nSurfaceTransaction_setPosition(surfaceControl, surfaceTransaction, 1, 0);
2230                         nSurfaceTransaction_setOnCompleteCallback(surfaceTransaction,
2231                                 false /* waitForFence */, onCompleteCallback);
2232                         nSurfaceTransaction_setOnCommitCallback(surfaceTransaction,
2233                                 onCommitCallback);
2234                         nSurfaceTransaction_apply(surfaceTransaction);
2235                         nSurfaceTransaction_delete(surfaceTransaction);
2236                     }
2237                 },
2238                 new RectChecker(DEFAULT_RECT) {
2239                     @Override
2240                     public PixelColor getExpectedColor(int x, int y) {
2241                         if (x >= 1) {
2242                             return RED;
2243                         } else {
2244                             return YELLOW;
2245                         }
2246                     }
2247                 });
2248 
2249         // Wait for callbacks to fire.
2250         onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
2251         onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
2252 
2253         // Validate we got callbacks with a valid latch time.
2254         assertTrue(onCommitCallback.mLatch.getCount() == 0);
2255         assertTrue(onCommitCallback.mCallbackTime > 0);
2256         assertTrue(onCommitCallback.mLatchTime > 0);
2257         assertTrue(onCompleteCallback.mLatch.getCount() == 0);
2258         assertTrue(onCompleteCallback.mCallbackTime > 0);
2259         assertTrue(onCompleteCallback.mLatchTime > 0);
2260 
2261         // Validate we received the callbacks in expected order and the latch times reported
2262         // matches.
2263         assertTrue(onCommitCallback.mCallbackTime <= onCompleteCallback.mCallbackTime);
2264         assertTrue(onCommitCallback.mLatchTime == onCompleteCallback.mLatchTime);
2265     }
2266 
2267     @Test
testSurfaceTransactionOnCommitCallback_withoutContext()2268     public void testSurfaceTransactionOnCommitCallback_withoutContext()
2269             throws InterruptedException {
2270         // Create and send an empty transaction with onCommit callbacks without context.
2271         long surfaceTransaction = nSurfaceTransaction_create();
2272         TimedTransactionListener onCommitCallback = new TimedTransactionListener();
2273         nSurfaceTransaction_setOnCommitCallbackWithoutContext(surfaceTransaction, onCommitCallback);
2274         nSurfaceTransaction_apply(surfaceTransaction);
2275         nSurfaceTransaction_delete(surfaceTransaction);
2276 
2277         // Wait for callbacks to fire.
2278         onCommitCallback.mLatch.await(1, TimeUnit.SECONDS);
2279 
2280         // Validate we got callbacks.
2281         assertEquals(0, onCommitCallback.mLatch.getCount());
2282         assertTrue(onCommitCallback.mCallbackTime > 0);
2283     }
2284 
2285     @Test
testSurfaceTransactionOnCompleteCallback_withoutContext()2286     public void testSurfaceTransactionOnCompleteCallback_withoutContext()
2287             throws InterruptedException {
2288         // Create and send an empty transaction with onComplete callbacks without context.
2289         long surfaceTransaction = nSurfaceTransaction_create();
2290         TimedTransactionListener onCompleteCallback = new TimedTransactionListener();
2291         nSurfaceTransaction_setOnCompleteCallbackWithoutContext(surfaceTransaction,
2292                 false /* waitForFence */, onCompleteCallback);
2293         nSurfaceTransaction_apply(surfaceTransaction);
2294         nSurfaceTransaction_delete(surfaceTransaction);
2295 
2296         // Wait for callbacks to fire.
2297         onCompleteCallback.mLatch.await(1, TimeUnit.SECONDS);
2298 
2299         // Validate we got callbacks.
2300         assertEquals(0, onCompleteCallback.mLatch.getCount());
2301         assertTrue(onCompleteCallback.mCallbackTime > 0);
2302     }
2303 
2304     @Test
testSetExtendedRangeBrightness()2305     public void testSetExtendedRangeBrightness() throws Exception {
2306         mActivity.awaitReadyState();
2307         Display display = mActivity.getDisplay();
2308         if (!display.isHdrSdrRatioAvailable()) {
2309             assertEquals(1.0f, display.getHdrSdrRatio(), 0.0001f);
2310         }
2311         // Set something super low so that if hdr/sdr ratio is available, we'll get some level
2312         // of HDR probably
2313         mActivity.getWindow().getAttributes().screenBrightness = 0.01f;
2314         // Wait for the screenBrightness to be picked up by VRI
2315         WidgetTestUtils.runOnMainAndDrawSync(mActivity.getParentFrameLayout(), () -> {});
2316         CountDownLatch hdrReady = new CountDownLatch(1);
2317         Exception[] listenerErrors = new Exception[1];
2318         if (display.isHdrSdrRatioAvailable()) {
2319             display.registerHdrSdrRatioChangedListener(Runnable::run, new Consumer<Display>() {
2320                 boolean mIsRegistered = true;
2321 
2322                 @Override
2323                 public void accept(Display updatedDisplay) {
2324                     try {
2325                         assertEquals(display.getDisplayId(), updatedDisplay.getDisplayId());
2326                         assertTrue(mIsRegistered);
2327                         if (display.getHdrSdrRatio() > 2.f) {
2328                             hdrReady.countDown();
2329                             display.unregisterHdrSdrRatioChangedListener(this);
2330                             mIsRegistered = false;
2331                         }
2332                     } catch (Exception e) {
2333                         synchronized (mActivity) {
2334                             listenerErrors[0] = e;
2335                             hdrReady.countDown();
2336                         }
2337                     }
2338                 }
2339             });
2340         } else {
2341             assertThrows(IllegalStateException.class, () ->
2342                     display.registerHdrSdrRatioChangedListener(Runnable::run, ignored -> {}));
2343         }
2344 
2345         final int extendedDataspace = DataSpace.pack(DataSpace.STANDARD_BT709,
2346                 DataSpace.TRANSFER_SRGB, DataSpace.RANGE_EXTENDED);
2347 
2348         verifyTest(
2349                 new BasicSurfaceHolderCallback() {
2350                     @Override
2351                     public void surfaceCreated(SurfaceHolder holder) {
2352                         long surfaceTransaction = nSurfaceTransaction_create();
2353                         long surfaceControl = createFromWindow(holder.getSurface());
2354                         setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
2355                                 DEFAULT_LAYOUT_HEIGHT, Color.WHITE);
2356                         nSurfaceTransaction_setDataSpace(surfaceControl, surfaceTransaction,
2357                                 extendedDataspace);
2358                         nSurfaceTransaction_setExtendedRangeBrightness(surfaceControl,
2359                                 surfaceTransaction, 3.f, 3.f);
2360                         nSurfaceTransaction_apply(surfaceTransaction);
2361                         nSurfaceTransaction_delete(surfaceTransaction);
2362                     }
2363                 },
2364                 new PixelChecker(Color.WHITE) { //10000
2365                     @Override
2366                     public boolean checkPixels(int pixelCount, int width, int height) {
2367                         return pixelCount > 9000 && pixelCount < 11000;
2368                     }
2369                 });
2370 
2371         // This isn't actually an error if it never happens, it's not _required_ that there's HDR
2372         // headroom available...
2373         if (display.isHdrSdrRatioAvailable()) {
2374             hdrReady.await(1, TimeUnit.SECONDS);
2375         }
2376 
2377         if (display.getHdrSdrRatio() > 2.f) {
2378             verifyTest(
2379                     new BasicSurfaceHolderCallback() {
2380                         @Override
2381                         public void surfaceCreated(SurfaceHolder holder) {
2382                             long surfaceTransaction = nSurfaceTransaction_create();
2383                             long surfaceControl = createFromWindow(holder.getSurface());
2384                             setSolidBuffer(surfaceControl, surfaceTransaction, DEFAULT_LAYOUT_WIDTH,
2385                                     DEFAULT_LAYOUT_HEIGHT, Color.WHITE);
2386                             nSurfaceTransaction_setDataSpace(surfaceControl, surfaceTransaction,
2387                                     extendedDataspace);
2388                             nSurfaceTransaction_setExtendedRangeBrightness(surfaceControl,
2389                                     surfaceTransaction, 3.f, 3.f);
2390                             nSurfaceTransaction_apply(surfaceTransaction);
2391                             nSurfaceTransaction_delete(surfaceTransaction);
2392                         }
2393                     },
2394                     new PixelChecker(Color.WHITE) { //10000
2395                         @Override
2396                         public boolean checkPixels(int pixelCount, int width, int height) {
2397                             return pixelCount > 9000 && pixelCount < 11000;
2398                         }
2399                     });
2400         }
2401 
2402         synchronized (mActivity) {
2403             if (listenerErrors[0] != null) {
2404                 throw listenerErrors[0];
2405             }
2406         }
2407     }
2408 
getStableHdrSdrRatio(Display display)2409     private float getStableHdrSdrRatio(Display display) {
2410         float ratio = -1f;
2411         float incomingRatio = display.getHdrSdrRatio();
2412         long startMillis = SystemClock.uptimeMillis();
2413         try {
2414             do {
2415                 ratio = incomingRatio;
2416                 TimeUnit.MILLISECONDS.sleep(500);
2417                 incomingRatio = display.getHdrSdrRatio();
2418                 // Bail if the ratio settled or if it's been way too long.
2419             } while (Math.abs(ratio - incomingRatio) > 0.01
2420                     && SystemClock.uptimeMillis() - startMillis < 10000);
2421         } catch (InterruptedException e) {
2422             throw new RuntimeException(e);
2423         }
2424         return ratio;
2425     }
2426 
2427     @Test
testSetDesiredHdrHeadroom()2428     public void testSetDesiredHdrHeadroom() throws Exception {
2429         mActivity.awaitReadyState();
2430         Display display = mActivity.getDisplay();
2431         assumeTrue(display.isHdrSdrRatioAvailable());
2432 
2433         final int dataspace = DataSpace.DATASPACE_BT2020_HLG;
2434 
2435         AtomicLong surfaceControlContainer = new AtomicLong();
2436 
2437         final CountDownLatch readyFence = new CountDownLatch(1);
2438         ASurfaceControlTestActivity.SurfaceHolderCallback surfaceHolderCallback =
2439                 new ASurfaceControlTestActivity.SurfaceHolderCallback(
2440                         new SurfaceHolderCallback(new BasicSurfaceHolderCallback() {
2441                             @Override
2442                             public void surfaceCreated(SurfaceHolder holder) {
2443                                 long surfaceTransaction = nSurfaceTransaction_create();
2444                                 long surfaceControl = createFromWindow(holder.getSurface());
2445                                 surfaceControlContainer.set(surfaceControl);
2446                                 setSolidBuffer(surfaceControl, surfaceTransaction,
2447                                         DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT, Color.WHITE);
2448                                 nSurfaceTransaction_setDataSpace(surfaceControl, surfaceTransaction,
2449                                         dataspace);
2450                                 nSurfaceTransaction_apply(surfaceTransaction);
2451                                 nSurfaceTransaction_delete(surfaceTransaction);
2452                             }
2453                         }),
2454                         readyFence,
2455                         mActivity.getParentFrameLayout().getRootSurfaceControl());
2456         mActivity.createSurface(surfaceHolderCallback);
2457         try {
2458             assertTrue("timeout", readyFence.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS));
2459         } catch (InterruptedException e) {
2460             Assert.fail("interrupted");
2461         }
2462 
2463         float headroom = getStableHdrSdrRatio(display);
2464         // Require some small threshold for allowable headroom
2465         assumeTrue(headroom > 1.02f);
2466         float targetHeadroom = 1.f + (headroom - 1.f) / 2;
2467 
2468         mActivity.runOnUiThread(() -> {
2469             long surfaceTransaction = nSurfaceTransaction_create();
2470             nSurfaceTransaction_setDesiredHdrHeadroom(
2471                     surfaceControlContainer.get(), surfaceTransaction, targetHeadroom);
2472             nSurfaceTransaction_apply(surfaceTransaction);
2473             nSurfaceTransaction_delete(surfaceTransaction);
2474         });
2475 
2476         assertTrue("Headroom restriction is not respected",
2477                 getStableHdrSdrRatio(display) <= (targetHeadroom + 0.01));
2478 
2479         mActivity.runOnUiThread(() -> {
2480             long surfaceTransaction = nSurfaceTransaction_create();
2481             nSurfaceTransaction_setDesiredHdrHeadroom(
2482                     surfaceControlContainer.get(), surfaceTransaction, 0.f);
2483             nSurfaceTransaction_apply(surfaceTransaction);
2484             nSurfaceTransaction_delete(surfaceTransaction);
2485         });
2486 
2487         assertTrue("Removed headroom restriction is not respected",
2488                 getStableHdrSdrRatio(display) > targetHeadroom);
2489     }
2490 }
2491