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