blob: b654c731b8dd22fb38f3de16353bbddc83316a58 [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.server.wm;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static android.server.wm.ActivityManagerTestBase.createFullscreenActivityScenarioRule;
import static android.server.wm.WindowManagerState.getLogicalDisplaySize;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Binder;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.view.cts.surfacevalidator.AnimationFactory;
import android.view.cts.surfacevalidator.CapturedActivity;
import android.view.cts.surfacevalidator.ISurfaceValidatorTestCase;
import android.view.cts.surfacevalidator.PixelChecker;
import android.view.cts.surfacevalidator.PixelColor;
import android.view.cts.surfacevalidator.SurfaceControlTestCase;
import android.view.Gravity;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import java.util.concurrent.CountDownLatch;
public class SurfacePackageFlickerTest {
private static final int DEFAULT_LAYOUT_WIDTH = 100;
private static final int DEFAULT_LAYOUT_HEIGHT = 100;
private static final int DEFAULT_BUFFER_WIDTH = 640;
private static final int DEFAULT_BUFFER_HEIGHT = 480;
@Rule
public final ActivityScenarioRule<CapturedActivity> mActivityRule =
createFullscreenActivityScenarioRule(CapturedActivity.class);
@Rule
public TestName mName = new TestName();
private CapturedActivity mActivity;
@Before
public void setup() {
mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
mActivity.dismissPermissionDialog();
mActivity.setLogicalDisplaySize(getLogicalDisplaySize());
}
/**
* Want to be especially sure we don't leave up the permission dialog, so try and dismiss
* after test.
*/
@After
public void tearDown() throws UiObjectNotFoundException {
mActivity.dismissPermissionDialog();
}
class SurfacePackageTestCase implements ISurfaceValidatorTestCase {
private final FrameLayout.LayoutParams mLayoutParams;
private final PixelChecker mPixelChecker;
private SurfaceView mSurfaceView;
private SurfaceControlViewHost mSurfaceControlViewHost;
private FrameLayout mParent;
private final CountDownLatch mFirstDrawLatch = new CountDownLatch(1);
private final Runnable mRecreateSurfaceViewCallback = new Runnable() {
public void run() {
if (mSurfaceControlViewHost == null) {
return;
}
mParent.removeView(mSurfaceView);
mSurfaceView = new SurfaceView(mActivity);
mSurfaceView.setZOrderOnTop(true);
mParent.addView(mSurfaceView, mLayoutParams);
mSurfaceView.setChildSurfacePackage(mSurfaceControlViewHost.getSurfacePackage());
mParent.post(mRecreateSurfaceViewCallback);
}
};
public SurfacePackageTestCase(PixelChecker pixelChecker,
int layoutWidth, int layoutHeight) {
mLayoutParams = new FrameLayout.LayoutParams(layoutWidth, layoutHeight,
Gravity.LEFT | Gravity.TOP);
mPixelChecker = pixelChecker;
}
@Override
public void start(Context context, FrameLayout parent) {
mParent = parent;
mSurfaceView = new SurfaceView(context);
mSurfaceView.setZOrderOnTop(true);
mParent.addView(mSurfaceView, mLayoutParams);
final View v = new View(mActivity);
v.setBackgroundColor(Color.GREEN);
mSurfaceControlViewHost = new SurfaceControlViewHost(mActivity, mActivity.getDisplay(),
new Binder());
mSurfaceControlViewHost.setView(v, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT);
mSurfaceView.setChildSurfacePackage(mSurfaceControlViewHost.getSurfacePackage());
v.getViewTreeObserver().registerFrameCommitCallback(() -> {
parent.post(mRecreateSurfaceViewCallback);
mFirstDrawLatch.countDown();
});
}
public void waitForReady() {
try {
mFirstDrawLatch.await();
} catch (Exception e) {
// Oh well
}
}
@Override
public void end() {
mSurfaceControlViewHost.release();
mParent.removeAllViews();
mSurfaceControlViewHost = null;
}
@Override
public boolean hasAnimation() {
return true;
}
@Override
public PixelChecker getChecker() {
return mPixelChecker;
}
@Override
public Rect getBoundsToCheck(FrameLayout parent) {
View boundsView = mParent;
Rect boundsToCheck = new Rect(0, 0, boundsView.getWidth(), boundsView.getHeight());
int[] topLeft = new int[2];
boundsView.getLocationOnScreen(topLeft);
boundsToCheck.offset(topLeft[0], topLeft[1]);
return boundsToCheck;
}
}
@Test
public void testSurfacePackageNoFlicker() throws Throwable {
// The basic operation of this test is to continually recreate
// SurfaceViews hosting a single green SurfacePackage.
// We verify that removing the old SurfaceView at the
// "same time" as reparenting the SurfacePackage to the new one
// results in a flicker free process.
PixelChecker pixelChecker = new PixelChecker(PixelColor.GREEN) {
@Override
public boolean checkPixels(int pixelCount, int width, int height) {
return pixelCount == DEFAULT_LAYOUT_WIDTH*DEFAULT_LAYOUT_HEIGHT;
}
};
SurfacePackageTestCase t = new SurfacePackageTestCase(
pixelChecker, DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT);
mActivity.verifyTest(t, mName);
}
}