19dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel/*
29dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * Copyright (C) 2015 The Android Open Source Project
39dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel *
49dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * Licensed under the Apache License, Version 2.0 (the "License");
59dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * you may not use this file except in compliance with the License.
69dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * You may obtain a copy of the License at
79dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel *
89dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel *      http://www.apache.org/licenses/LICENSE-2.0
99dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel *
109dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * Unless required by applicable law or agreed to in writing, software
119dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * distributed under the License is distributed on an "AS IS" BASIS,
129dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * See the License for the specific language governing permissions and
149dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * limitations under the License.
159dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel */
169dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelpackage android.surfacecomposition;
179dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
189dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport java.util.Random;
199dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
209dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.content.Context;
219dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.graphics.Canvas;
229dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.graphics.Paint;
239dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.view.Surface;
249dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.view.SurfaceHolder;
259dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelimport android.view.SurfaceView;
269dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
279dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel/**
289dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * This provides functionality to measure Surface update frame rate. The idea is to
299dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * constantly invalidates Surface in a separate thread. Lowest possible way is to
309dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * use SurfaceView which works with Surface. This gives a very small overhead
319dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * and very close to Android internals. Note, that lockCanvas is blocking
329dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * methods and it returns once SurfaceFlinger consumes previous buffer. This
339dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel * gives the change to measure real performance of Surface compositor.
349dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel */
359dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmelpublic class CustomSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
369dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private final static long DURATION_TO_WARMUP_MS = 50;
379dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private final static long DURATION_TO_MEASURE_ROUGH_MS = 500;
389dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private final static long DURATION_TO_MEASURE_PRECISE_MS = 3000;
399dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private final static Random mRandom = new Random();
409dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
419dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private final Object mSurfaceLock = new Object();
429dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private Surface mSurface;
439dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private boolean mDrawNameOnReady = true;
449dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private boolean mSurfaceWasChanged = false;
459dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private String mName;
469dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private Canvas mCanvas;
479dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
489dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    class ValidateThread extends Thread {
499dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        private double mFPS = 0.0f;
509dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        // Used to support early exit and prevent long computation.
519dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        private double mBadFPS;
529dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        private double mPerfectFPS;
539dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
549dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        ValidateThread(double badFPS, double perfectFPS) {
559dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mBadFPS = badFPS;
569dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mPerfectFPS = perfectFPS;
579dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
589dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
599dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        public void run() {
609dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            long startTime = System.currentTimeMillis();
619dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            while (System.currentTimeMillis() - startTime < DURATION_TO_WARMUP_MS) {
629dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                invalidateSurface(false);
639dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
649dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
659dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            startTime = System.currentTimeMillis();
669dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            long endTime;
679dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            int frameCnt = 0;
689dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            while (true) {
699dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                invalidateSurface(false);
709dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                endTime = System.currentTimeMillis();
719dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                ++frameCnt;
729dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                mFPS = (double)frameCnt * 1000.0 / (endTime - startTime);
739dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                if ((endTime - startTime) >= DURATION_TO_MEASURE_ROUGH_MS) {
749dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    // Test if result looks too bad or perfect and stop early.
759dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    if (mFPS <= mBadFPS || mFPS >= mPerfectFPS) {
769dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                        break;
779dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    }
789dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
799dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                if ((endTime - startTime) >= DURATION_TO_MEASURE_PRECISE_MS) {
809dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    break;
819dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
829dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
839dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
849dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
859dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        public double getFPS() {
869dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            return mFPS;
879dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
889dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
899dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
909dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public CustomSurfaceView(Context context, String name) {
919dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        super(context);
929dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        mName = name;
939dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        getHolder().addCallback(this);
949dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
959dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
969dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void setMode(int pixelFormat, boolean drawNameOnReady) {
979dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        mDrawNameOnReady = drawNameOnReady;
989dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        getHolder().setFormat(pixelFormat);
999dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1009dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1019dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void acquireCanvas() {
1029dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1039dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mCanvas != null) {
1049dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                throw new RuntimeException("Surface canvas was already acquired.");
1059dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1069dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface != null) {
1079dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                mCanvas = mSurface.lockCanvas(null);
1089dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1099dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1109dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1119dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1129dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void releaseCanvas() {
1139dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1149dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mCanvas != null) {
1159dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                if (mSurface == null) {
1169dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    throw new RuntimeException(
1179dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                            "Surface was destroyed but canvas was not released.");
1189dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
1199dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                mSurface.unlockCanvasAndPost(mCanvas);
1209dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                mCanvas = null;
1219dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1229dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1239dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1249dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1259dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    /**
1269dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * Invalidate surface.
1279dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     */
1289dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    private void invalidateSurface(boolean drawSurfaceId) {
1299dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1309dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface != null) {
1319dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                Canvas canvas = mSurface.lockCanvas(null);
1329dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                // Draw surface name for debug purpose only. This does not affect the test
1339dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                // because it is drawn only during allocation.
1349dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                if (drawSurfaceId) {
1359dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    int textSize = canvas.getHeight() / 24;
1369dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    Paint paint = new Paint();
1379dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    paint.setTextSize(textSize);
1389dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    int textWidth = (int)(paint.measureText(mName) + 0.5f);
1399dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    int x = mRandom.nextInt(canvas.getWidth() - textWidth);
1409dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    int y = textSize + mRandom.nextInt(canvas.getHeight() - textSize);
1419dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    // Create effect of fog to visually control correctness of composition.
1429dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    paint.setColor(0xFFFF8040);
1439dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    canvas.drawARGB(32, 255, 255, 255);
1449dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    canvas.drawText(mName, x, y, paint);
1459dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
1469dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                mSurface.unlockCanvasAndPost(canvas);
1479dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1489dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1499dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1509dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1519dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    /**
1529dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * Wait until surface is created and ready to use or return immediately if surface
1539dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * already exists.
1549dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     */
1559dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void waitForSurfaceReady() {
1569dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1579dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface == null) {
1589dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                try {
1599dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    mSurfaceLock.wait(5000);
1609dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                } catch(InterruptedException e) {
1619dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    e.printStackTrace();
1629dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
1639dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1649dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface == null)
1659dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                throw new RuntimeException("Surface is not ready.");
1669dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceWasChanged = false;
1679dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1689dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1699dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1709dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    /**
1719dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * Wait until surface is destroyed or return immediately if surface does not exist.
1729dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     */
1739dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void waitForSurfaceDestroyed() {
1749dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1759dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface != null) {
1769dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                try {
1779dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    mSurfaceLock.wait(5000);
1789dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                } catch(InterruptedException e) {
1799dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                    e.printStackTrace();
1809dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                }
1819dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1829dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurface != null)
1839dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                throw new RuntimeException("Surface still exists.");
1849dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceWasChanged = false;
1859dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1869dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1879dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
1889dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    /**
1899dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * Validate that surface has not been changed since waitForSurfaceReady or
1909dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     * waitForSurfaceDestroyed.
1919dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel     */
1929dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void validateSurfaceNotChanged() {
1939dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
1949dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mSurfaceWasChanged) {
1959dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                throw new RuntimeException("Surface was changed during the test execution.");
1969dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
1979dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
1989dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
1999dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
2009dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public double measureFPS(double badFPS, double perfectFPS) {
2019dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        try {
2029dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            ValidateThread validateThread = new ValidateThread(badFPS, perfectFPS);
2039dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            validateThread.start();
2049dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            validateThread.join();
2059dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            return validateThread.getFPS();
2069dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        } catch (InterruptedException e) {
2079dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            throw new RuntimeException(e);
2089dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
2099dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
2109dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
2119dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    @Override
2129dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void surfaceCreated(SurfaceHolder holder) {
2139dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
2149dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceWasChanged = true;
2159dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
2169dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
2179dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
2189dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    @Override
2199dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
2209dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        // This method is always called at least once, after surfaceCreated.
2219dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
2229dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurface = holder.getSurface();
2239dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            // We only need to invalidate the surface for the compositor performance test so that
2249dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            // it gets included in the composition process. For allocation performance we
2259dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            // don't need to invalidate surface and this allows us to remove non-necessary
2269dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            // surface invalidation from the test.
2279dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            if (mDrawNameOnReady) {
2289dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel                invalidateSurface(true);
2299dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            }
2309dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceWasChanged = true;
2319dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceLock.notify();
2329dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
2339dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
2349dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel
2359dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    @Override
2369dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    public void surfaceDestroyed(SurfaceHolder holder) {
2379dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        synchronized (mSurfaceLock) {
2389dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurface = null;
2399dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceWasChanged = true;
2409dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel            mSurfaceLock.notify();
2419dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel        }
2429dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel    }
2439dbde7b09f2366d2a239b1a4c234d5cf2de51739Yury Khmel}
244