1 /*
2  * Copyright 2019 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 package android.view.surfacecontrol.cts;
17 
18 import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
19 import static android.server.wm.BuildUtils.HW_TIMEOUT_MULTIPLIER;
20 
21 import android.content.Context;
22 import android.graphics.Color;
23 import android.os.Binder;
24 import android.view.Gravity;
25 import android.view.SurfaceControlViewHost;
26 import android.view.SurfaceView;
27 import android.view.View;
28 import android.view.cts.surfacevalidator.CapturedActivity;
29 import android.view.cts.surfacevalidator.ISurfaceValidatorTestCase;
30 import android.view.cts.surfacevalidator.PixelChecker;
31 import android.widget.FrameLayout;
32 
33 import androidx.test.ext.junit.rules.ActivityScenarioRule;
34 
35 import org.junit.Before;
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.rules.TestName;
39 
40 import java.util.concurrent.CountDownLatch;
41 import java.util.concurrent.TimeUnit;
42 
43 public class SurfacePackageFlickerTest {
44     private static final int DEFAULT_LAYOUT_WIDTH = 100;
45     private static final int DEFAULT_LAYOUT_HEIGHT = 100;
46 
47     @Rule
48     public final ActivityScenarioRule<CapturedActivity> mActivityRule =
49                 createFullscreenActivityScenarioRule(CapturedActivity.class);
50 
51     @Rule
52     public TestName mName = new TestName();
53     private CapturedActivity mActivity;
54 
55     @Before
setup()56     public void setup() {
57         mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
58     }
59 
60     class SurfacePackageTestCase implements ISurfaceValidatorTestCase {
61         private final FrameLayout.LayoutParams mLayoutParams;
62         private final PixelChecker mPixelChecker;
63         private SurfaceView mSurfaceView;
64         private SurfaceControlViewHost mSurfaceControlViewHost;
65         private FrameLayout mParent;
66         private final CountDownLatch mFirstDrawLatch = new CountDownLatch(1);
67 
68 
69         private final Runnable mRecreateSurfaceViewCallback = new Runnable() {
70                 public void run() {
71                     if (mSurfaceControlViewHost == null) {
72                         return;
73                     }
74                     mParent.removeView(mSurfaceView);
75                     mSurfaceView = new SurfaceView(mActivity);
76                     mSurfaceView.setZOrderOnTop(true);
77                     mParent.addView(mSurfaceView, mLayoutParams);
78                     mSurfaceView.setChildSurfacePackage(mSurfaceControlViewHost.getSurfacePackage());
79                     mParent.post(mRecreateSurfaceViewCallback);
80                 }
81         };
82 
SurfacePackageTestCase(PixelChecker pixelChecker, int layoutWidth, int layoutHeight)83         public SurfacePackageTestCase(PixelChecker pixelChecker,
84                                       int layoutWidth, int layoutHeight) {
85             mLayoutParams = new FrameLayout.LayoutParams(layoutWidth, layoutHeight,
86                 Gravity.LEFT | Gravity.TOP);
87             mPixelChecker = pixelChecker;
88         }
89 
90         @Override
start(Context context, FrameLayout parent)91         public void start(Context context, FrameLayout parent) {
92             mParent = parent;
93             mSurfaceView = new SurfaceView(context);
94             mSurfaceView.setZOrderOnTop(true);
95             mParent.addView(mSurfaceView, mLayoutParams);
96 
97             final View v = new View(mActivity);
98             v.setBackgroundColor(Color.GREEN);
99 
100             mSurfaceControlViewHost = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
101                 new Binder());
102             mSurfaceControlViewHost.setView(v, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT);
103             mSurfaceView.setChildSurfacePackage(mSurfaceControlViewHost.getSurfacePackage());
104 
105             v.getViewTreeObserver().registerFrameCommitCallback(() -> {
106                 parent.post(mRecreateSurfaceViewCallback);
107                 mFirstDrawLatch.countDown();
108             });
109         }
110 
waitForReady()111         public boolean waitForReady() {
112             try {
113                 return mFirstDrawLatch.await(5L * HW_TIMEOUT_MULTIPLIER, TimeUnit.SECONDS);
114             } catch (Exception e) {
115                 return false;
116                 // Oh well
117             }
118         }
119 
120         @Override
end()121         public void end() {
122             mSurfaceControlViewHost.release();
123             mParent.removeAllViews();
124             mSurfaceControlViewHost = null;
125         }
126 
127         @Override
getChecker()128         public PixelChecker getChecker() {
129             return mPixelChecker;
130         }
131     }
132 
133     @Test
testSurfacePackageNoFlicker()134     public void testSurfacePackageNoFlicker() throws Throwable {
135         // The basic operation of this test is to continually recreate
136         // SurfaceViews hosting a single green SurfacePackage.
137         // We verify that removing the old SurfaceView at the
138         // "same time" as reparenting the SurfacePackage to the new one
139         // results in a flicker free process.
140         PixelChecker pixelChecker = new PixelChecker(Color.GREEN) {
141             @Override
142             public boolean checkPixels(int pixelCount, int width, int height) {
143                 return pixelCount == DEFAULT_LAYOUT_WIDTH*DEFAULT_LAYOUT_HEIGHT;
144             }
145         };
146         SurfacePackageTestCase t = new SurfacePackageTestCase(
147                 pixelChecker, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT);
148         mActivity.verifyTest(t, mName);
149     }
150 }
151