154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project/* 254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * you may not use this file except in compliance with the License. 654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * You may obtain a copy of the License at 754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * 1054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * See the License for the specific language governing permissions and 1454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * limitations under the License. 1554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 1654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectpackage android.view; 1854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 193b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawaimport static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 20d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carrimport static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER; 213b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawaimport static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER; 22d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carrimport static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER; 23d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 2454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.content.Context; 2564f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshimaimport android.content.res.CompatibilityInfo.Translator; 2667e2ae86396c6d0f989285275cbf908dee5e71f7Aurimas Liutikasimport android.content.res.Configuration; 2754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.Canvas; 2854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.PixelFormat; 2954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.PorterDuff; 3054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.Rect; 3154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.graphics.Region; 323b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawaimport android.os.Build; 3354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.os.Handler; 34552355529335c0c3593b0f79f54d84a90b93a62cRobert Carrimport android.os.IBinder; 357992500d540e5411017d90da3ee4b02bbe283906John Reckimport android.os.Looper; 3654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.os.SystemClock; 3754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.util.AttributeSet; 3854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport android.util.Log; 3954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 4025cfa134835e3791bdb6572f5e25cf4599015678Robert Carrimport com.android.internal.view.SurfaceCallbackHelper; 4167e2ae86396c6d0f989285275cbf908dee5e71f7Aurimas Liutikas 429bdf576615231e4b9693f08bfe3dc886c2edf49eJon Larimerimport java.util.ArrayList; 4354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Projectimport java.util.concurrent.locks.ReentrantLock; 4454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 4554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project/** 4654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Provides a dedicated drawing surface embedded inside of a view hierarchy. 4754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * You can control the format of this surface and, if you like, its size; the 4854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * SurfaceView takes care of placing the surface at the correct location on the 4954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * screen 50a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 5154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <p>The surface is Z ordered so that it is behind the window holding its 5254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * SurfaceView; the SurfaceView punches a hole in its window to allow its 53c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * surface to be displayed. The view hierarchy will take care of correctly 5454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * compositing with the Surface any siblings of the SurfaceView that would 55c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * normally appear on top of it. This can be used to place overlays such as 5654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * buttons on top of the Surface, though note however that it can have an 5754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * impact on performance since a full alpha-blended composite will be performed 5854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * each time the Surface changes. 59a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 60c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * <p> The transparent region that makes the surface visible is based on the 61c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * layout positions in the view hierarchy. If the post-layout transform 62c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * properties are used to draw a sibling view on top of the SurfaceView, the 63c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * view may not be properly composited with the surface. 64c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * 6554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <p>Access to the underlying surface is provided via the SurfaceHolder interface, 6654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * which can be retrieved by calling {@link #getHolder}. 67a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 6854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <p>The Surface will be created for you while the SurfaceView's window is 6954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated} 7054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the 7154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Surface is created and destroyed as the window is shown and hidden. 72a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 7354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <p>One of the purposes of this class is to provide a surface in which a 74c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * secondary thread can render into the screen. If you are going to use it 7554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * this way, you need to be aware of some threading semantics: 76a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 7754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <ul> 7854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <li> All SurfaceView and 7954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called 8054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * from the thread running the SurfaceView's window (typically the main thread 81c9f345ff7bc59916d5168d49d9312b2ff7a07daaJesse Hall * of the application). They thus need to correctly synchronize with any 8254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * state that is also touched by the drawing thread. 8354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * <li> You must ensure that the drawing thread only touches the underlying 8454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Surface while it is valid -- between 8554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()} 8654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * and 8754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}. 8854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * </ul> 896ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * 906ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * <p class="note"><strong>Note:</strong> Starting in platform version 916ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * {@link android.os.Build.VERSION_CODES#N}, SurfaceView's window position is 926ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * updated synchronously with other View rendering. This means that translating 936ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * and scaling a SurfaceView on screen will not cause rendering artifacts. Such 946ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * artifacts may occur on previous versions of the platform when its window is 956ee192f4e981845db5fdff127bf2ee990cd05dbfChris Craik * positioned asynchronously.</p> 9654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 97414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carrpublic class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback { 98d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private static final String TAG = "SurfaceView"; 99d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private static final boolean DEBUG = false; 10054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 10154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final ArrayList<SurfaceHolder.Callback> mCallbacks 10254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project = new ArrayList<SurfaceHolder.Callback>(); 10354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 104f013e1afd1e68af5e3b868c26a653bbfb39538f8The Android Open Source Project final int[] mLocation = new int[2]; 105a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 10654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final ReentrantLock mSurfaceLock = new ReentrantLock(); 10761566cc1932468720a831ad5cbc68ee080d613c9Dianne Hackborn final Surface mSurface = new Surface(); // Current surface in use 10854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mDrawingStopped = true; 109d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // We use this to track if the application has produced a frame 110d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // in to the Surface. Up until that point, we should be careful not to punch 111d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // holes. 112d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr boolean mDrawFinished = false; 113d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 114d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final Rect mScreenRect = new Rect(); 115d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceSession mSurfaceSession; 11654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 117d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceControl mSurfaceControl; 1183bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr // In the case of format changes we switch out the surface in-place 1193bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr // we need to preserve the old one until the new one has drawn. 1203bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr SurfaceControl mDeferredDestroySurfaceControl; 1213387913237b1f73a775d10e83e1feb8a9b5d1831Robert Carr final Rect mTmpRect = new Rect(); 122694f79b5d1196640d1beb680b7d1fc68e6e77cbdDianne Hackborn final Configuration mConfiguration = new Configuration(); 123a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 124d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr int mSubLayer = APPLICATION_MEDIA_SUBLAYER; 125a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 12654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mIsCreating = false; 127f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck private volatile boolean mRtHandlingPositionUpdates = false; 12854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 129f648108f83d4e74811919e9811efb8fcc184b8a3John Reck private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener 130e2af5c882b146c3a8c7a37f093d13c8b386e8ebaDianne Hackborn = new ViewTreeObserver.OnScrollChangedListener() { 131a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 132e2af5c882b146c3a8c7a37f093d13c8b386e8ebaDianne Hackborn public void onScrollChanged() { 133d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 134e2af5c882b146c3a8c7a37f093d13c8b386e8ebaDianne Hackborn } 135e2af5c882b146c3a8c7a37f093d13c8b386e8ebaDianne Hackborn }; 136a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 137f648108f83d4e74811919e9811efb8fcc184b8a3John Reck private final ViewTreeObserver.OnPreDrawListener mDrawListener = 138f648108f83d4e74811919e9811efb8fcc184b8a3John Reck new ViewTreeObserver.OnPreDrawListener() { 139f648108f83d4e74811919e9811efb8fcc184b8a3John Reck @Override 140f648108f83d4e74811919e9811efb8fcc184b8a3John Reck public boolean onPreDraw() { 141f648108f83d4e74811919e9811efb8fcc184b8a3John Reck // reposition ourselves where the surface is 142f648108f83d4e74811919e9811efb8fcc184b8a3John Reck mHaveFrame = getWidth() > 0 && getHeight() > 0; 143d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 144f648108f83d4e74811919e9811efb8fcc184b8a3John Reck return true; 145f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 146f648108f83d4e74811919e9811efb8fcc184b8a3John Reck }; 147f648108f83d4e74811919e9811efb8fcc184b8a3John Reck 14854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mRequestedVisible = false; 1496b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian boolean mWindowVisibility = false; 150d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr boolean mLastWindowVisibility = false; 1516b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian boolean mViewVisibility = false; 152414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr boolean mWindowStopped = false; 153414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 15454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int mRequestedWidth = -1; 15554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int mRequestedHeight = -1; 156d6ddcb7f00a7af95b452233d965b922632f78f21Mathias Agopian /* Set SurfaceView's format to 565 by default to maintain backward 157d6ddcb7f00a7af95b452233d965b922632f78f21Mathias Agopian * compatibility with applications assuming this format. 158d6ddcb7f00a7af95b452233d965b922632f78f21Mathias Agopian */ 159d6ddcb7f00a7af95b452233d965b922632f78f21Mathias Agopian int mRequestedFormat = PixelFormat.RGB_565; 16054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 16154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mHaveFrame = false; 1626d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn boolean mSurfaceCreated = false; 16354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project long mLastLockTime = 0; 164a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 16554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean mVisible = false; 16664aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr int mWindowSpaceLeft = -1; 16764aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr int mWindowSpaceTop = -1; 168d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr int mSurfaceWidth = -1; 169d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr int mSurfaceHeight = -1; 17054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int mFormat = -1; 17154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final Rect mSurfaceFrame = new Rect(); 172726426ee736929e605742bfa52bca4b20095921dDianne Hackborn int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1; 17364f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima private Translator mTranslator; 174f2499fa434521a8948387afe8f0acd4f39620500Romain Guy 17501d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy private boolean mGlobalListenersAdded; 1768508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr private boolean mAttachedToWindow; 177f2499fa434521a8948387afe8f0acd4f39620500Romain Guy 178d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private int mSurfaceFlags = SurfaceControl.HIDDEN; 179d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 1808508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr private int mPendingReportDraws; 1818508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr 18254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public SurfaceView(Context context) { 183768ca7d19bbd7ba73dee662480ea5a53ae3fbbe9Alan Viverette this(context, null); 18454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 185a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 18654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public SurfaceView(Context context, AttributeSet attrs) { 187768ca7d19bbd7ba73dee662480ea5a53ae3fbbe9Alan Viverette this(context, attrs, 0); 18854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 18954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 190617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr) { 191768ca7d19bbd7ba73dee662480ea5a53ae3fbbe9Alan Viverette this(context, attrs, defStyleAttr, 0); 192617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 193617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 194617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 195617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 1963acf0382da22cda88234e599cd81b1ff5441cc35John Reck mRenderNode.requestPositionUpdates(this); 197d6ddcb7f00a7af95b452233d965b922632f78f21Mathias Agopian 19854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project setWillNotDraw(true); 19954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 200a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 20154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project /** 20254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * Return the SurfaceHolder providing access and control over this 20354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * SurfaceView's underlying surface. 204a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 20554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project * @return SurfaceHolder The holder of the surface. 20654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project */ 20754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public SurfaceHolder getHolder() { 20854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return mSurfaceHolder; 20954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 21054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 211414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr private void updateRequestedVisibility() { 212414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped; 213414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr } 214414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 215414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr /** @hide */ 216414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr @Override 217414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr public void windowStopped(boolean stopped) { 218414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr mWindowStopped = stopped; 219414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr updateRequestedVisibility(); 220414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr updateSurface(); 221414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr } 222414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 22354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 22454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void onAttachedToWindow() { 22554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.onAttachedToWindow(); 226414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 227414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr getViewRootImpl().addWindowStoppedCallback(this); 22800177cc4479c4309a0802c5ac3970b8ed3df3d8bRobert Carr mWindowStopped = false; 229414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 2306b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian mViewVisibility = getVisibility() == VISIBLE; 231414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr updateRequestedVisibility(); 23201d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy 2338508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr mAttachedToWindow = true; 23401d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy if (!mGlobalListenersAdded) { 23501d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy ViewTreeObserver observer = getViewTreeObserver(); 23601d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy observer.addOnScrollChangedListener(mScrollChangedListener); 23701d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy observer.addOnPreDrawListener(mDrawListener); 23801d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy mGlobalListenersAdded = true; 23901d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy } 24054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 24154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 24254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 24354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void onWindowVisibilityChanged(int visibility) { 24454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.onWindowVisibilityChanged(visibility); 2456b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian mWindowVisibility = visibility == VISIBLE; 246414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr updateRequestedVisibility(); 247d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 2486b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian } 2496b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian 2506b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian @Override 2516b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian public void setVisibility(int visibility) { 2526b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian super.setVisibility(visibility); 2536b7f1a62b5094fc72765a2537ee0760572df0950Mathias Agopian mViewVisibility = visibility == VISIBLE; 254414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr boolean newRequestedVisible = mWindowVisibility && mViewVisibility && !mWindowStopped; 255cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian if (newRequestedVisible != mRequestedVisible) { 256cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // our base class (View) invalidates the layout only when 257cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // we go from/to the GONE state. However, SurfaceView needs 258cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // to request a re-layout when the visibility changes at all. 259cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // This is needed because the transparent region is computed 260cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // as part of the layout phase, and it changes (obviously) when 261cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian // the visibility changes. 262cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian requestLayout(); 263cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian } 264cbeb33249d5beec7903f18269c991a5515c5d981Mathias Agopian mRequestedVisible = newRequestedVisible; 265d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 26654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 267afc3e11f10828e113331eb24b65e4f9759f67747Romain Guy 268b53670aecf2699022dffbf9400267ccf147eba64Robert Carr private void performDrawFinished() { 269b53670aecf2699022dffbf9400267ccf147eba64Robert Carr if (mPendingReportDraws > 0) { 270b53670aecf2699022dffbf9400267ccf147eba64Robert Carr mDrawFinished = true; 271b53670aecf2699022dffbf9400267ccf147eba64Robert Carr if (mAttachedToWindow) { 272b53670aecf2699022dffbf9400267ccf147eba64Robert Carr mParent.requestTransparentRegion(SurfaceView.this); 273b53670aecf2699022dffbf9400267ccf147eba64Robert Carr 274b53670aecf2699022dffbf9400267ccf147eba64Robert Carr notifyDrawFinished(); 275b53670aecf2699022dffbf9400267ccf147eba64Robert Carr invalidate(); 276b53670aecf2699022dffbf9400267ccf147eba64Robert Carr } 277b53670aecf2699022dffbf9400267ccf147eba64Robert Carr } else { 278b53670aecf2699022dffbf9400267ccf147eba64Robert Carr Log.e(TAG, System.identityHashCode(this) + "finished drawing" 279b53670aecf2699022dffbf9400267ccf147eba64Robert Carr + " but no pending report draw (extra call" 280b53670aecf2699022dffbf9400267ccf147eba64Robert Carr + " to draw completion runnable?)"); 281b53670aecf2699022dffbf9400267ccf147eba64Robert Carr } 282b53670aecf2699022dffbf9400267ccf147eba64Robert Carr } 283b53670aecf2699022dffbf9400267ccf147eba64Robert Carr 2848508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr void notifyDrawFinished() { 2858508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr ViewRootImpl viewRoot = getViewRootImpl(); 2868508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr if (viewRoot != null) { 2878508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr viewRoot.pendingDrawFinished(); 2888508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr } 2898508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr mPendingReportDraws--; 2908508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr } 2918508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr 29254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 29377e4a5250fc6df451999efe508f57968a44b603fJohn Reck protected void onDetachedFromWindow() { 2940c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin ViewRootImpl viewRoot = getViewRootImpl(); 2950c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin // It's possible to create a SurfaceView using the default constructor and never 2960c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin // attach it to a view hierarchy, this is a common use case when dealing with 2970c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin // OpenGL. A developer will probably create a new GLSurfaceView, and let it manage 2980c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin // the lifecycle. Instead of attaching it to a view, he/she can just pass 2990c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin // the SurfaceHolder forward, most live wallpapers do it. 3000c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin if (viewRoot != null) { 3010c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin viewRoot.removeWindowStoppedCallback(this); 3020c207340b9aaf005da21b15c984e73eec8efacdeLucas Dupin } 303414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 3048508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr mAttachedToWindow = false; 30501d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy if (mGlobalListenersAdded) { 30601d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy ViewTreeObserver observer = getViewTreeObserver(); 30701d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy observer.removeOnScrollChangedListener(mScrollChangedListener); 30801d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy observer.removeOnPreDrawListener(mDrawListener); 30901d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy mGlobalListenersAdded = false; 31001d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy } 31101d5edc49ae8995aabffe1a30bfd966faaf70bd6Romain Guy 3128508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr while (mPendingReportDraws > 0) { 3138508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr notifyDrawFinished(); 3148508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr } 3158508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr 31654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mRequestedVisible = false; 317d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 318d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 319d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mSurfaceControl != null) { 320d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.destroy(); 32154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 322d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl = null; 32354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 324d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mHaveFrame = false; 325414ebc6ac8dcc972cc97f637e21ac09e59bef112Robert Carr 32677e4a5250fc6df451999efe508f57968a44b603fJohn Reck super.onDetachedFromWindow(); 32754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 32854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 32954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 33054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 331189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn int width = mRequestedWidth >= 0 332189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn ? resolveSizeAndState(mRequestedWidth, widthMeasureSpec, 0) 333189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn : getDefaultSize(0, widthMeasureSpec); 334189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn int height = mRequestedHeight >= 0 335189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn ? resolveSizeAndState(mRequestedHeight, heightMeasureSpec, 0) 336189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn : getDefaultSize(0, heightMeasureSpec); 33754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project setMeasuredDimension(width, height); 33854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 339a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 340ef11530874f86570aa04a10c16a416b274b3fdf5Mathias Agopian /** @hide */ 34154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 342995bb9d24d3b278939a01e1d05c2b7f337ab0565Mathias Agopian protected boolean setFrame(int left, int top, int right, int bottom) { 343995bb9d24d3b278939a01e1d05c2b7f337ab0565Mathias Agopian boolean result = super.setFrame(left, top, right, bottom); 344d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 345995bb9d24d3b278939a01e1d05c2b7f337ab0565Mathias Agopian return result; 34654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 34754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 34854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 34954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public boolean gatherTransparentRegion(Region region) { 3503ca12be7963b0d018bade286bf4d14cf9938bd6aRobert Carr if (isAboveParent() || !mDrawFinished) { 3511cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn return super.gatherTransparentRegion(region); 3521cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn } 353a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 35454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project boolean opaque = true; 3554702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) { 35654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // this view draws, remove it from the transparent region 35754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project opaque = super.gatherTransparentRegion(region); 35854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } else if (region != null) { 35954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int w = getWidth(); 36054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int h = getHeight(); 36154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (w>0 && h>0) { 36254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project getLocationInWindow(mLocation); 36354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // otherwise, punch a hole in the whole hierarchy 36454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int l = mLocation[0]; 36554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int t = mLocation[1]; 36654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project region.op(l, t, l+w, t+h, Region.Op.UNION); 36754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 36854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 36954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (PixelFormat.formatHasAlpha(mRequestedFormat)) { 37054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project opaque = false; 37154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 37254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return opaque; 37354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 37454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 37554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 37654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void draw(Canvas canvas) { 377d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mDrawFinished && !isAboveParent()) { 3781cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn // draw() is not called when SKIP_DRAW is set 3794702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) { 3801cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn // punch a whole in the view-hierarchy below us 3811cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn canvas.drawColor(0, PorterDuff.Mode.CLEAR); 3821cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn } 38354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 38454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.draw(canvas); 38554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 38654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 38754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project @Override 38854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project protected void dispatchDraw(Canvas canvas) { 389d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mDrawFinished && !isAboveParent()) { 390d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // draw() is not called when SKIP_DRAW is set 3914702a856973a553deb82f71b1d3b6c3db5dbf4baDianne Hackborn if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { 3921cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn // punch a whole in the view-hierarchy below us 3931cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn canvas.drawColor(0, PorterDuff.Mode.CLEAR); 3941cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn } 39554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 39654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project super.dispatchDraw(canvas); 39754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 39854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 399c4d5d02667af6989a3121072871f6a4b1e68b594Dianne Hackborn /** 40029e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * Control whether the surface view's surface is placed on top of another 40129e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * regular surface view in the window (but still behind the window itself). 40229e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * This is typically used to place overlays on top of an underlying media 40329e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * surface view. 404a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 40529e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * <p>Note that this must be set before the surface view's containing 40629e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * window is attached to the window manager. 407a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 40829e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}. 40929e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn */ 41029e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn public void setZOrderMediaOverlay(boolean isMediaOverlay) { 411d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSubLayer = isMediaOverlay 412d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER; 41329e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn } 414a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 41529e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn /** 4161cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * Control whether the surface view's surface is placed on top of its 4171cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * window. Normally it is placed behind the window, to allow it to 4181cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * (for the most part) appear to composite with the views in the 4191cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * hierarchy. By setting this, you cause it to be placed above the 4201cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * window. This means that none of the contents of the window this 4211cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * SurfaceView is in will be visible on top of its surface. 422a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 4231cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * <p>Note that this must be set before the surface view's containing 4241cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn * window is attached to the window manager. 425a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin * 42629e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}. 4271cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn */ 42829e4a3c566f435c32f0b95e4ac8e8b33cac6fabaDianne Hackborn public void setZOrderOnTop(boolean onTop) { 429ecde72fe411811ca02a2565bf73b86e6e8ddc76bDerek Sollenberger if (onTop) { 430d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSubLayer = APPLICATION_PANEL_SUBLAYER; 431ecde72fe411811ca02a2565bf73b86e6e8ddc76bDerek Sollenberger } else { 432d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSubLayer = APPLICATION_MEDIA_SUBLAYER; 433ecde72fe411811ca02a2565bf73b86e6e8ddc76bDerek Sollenberger } 4341cd403eaac24e0e84619dea07e2d1d60e58e1fd2Dianne Hackborn } 435f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown 436f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown /** 437f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * Control whether the surface view's content should be treated as secure, 438f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * preventing it from appearing in screenshots or from being viewed on 439f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * non-secure displays. 440f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * 441f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * <p>Note that this must be set before the surface view's containing 442f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * window is attached to the window manager. 443f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * 444f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * <p>See {@link android.view.Display#FLAG_SECURE} for details. 445f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * 446f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown * @param isSecure True if the surface view is secure. 447f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown */ 448f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown public void setSecure(boolean isSecure) { 449f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (isSecure) { 450d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFlags |= SurfaceControl.SECURE; 451f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } else { 452d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFlags &= ~SurfaceControl.SECURE; 453f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 454f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 455f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown 456552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr private void updateOpaqueFlag() { 457851e7e43941739398d629f86e3affb2866958ee9Robert Carr if (!PixelFormat.formatHasAlpha(mRequestedFormat)) { 458552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mSurfaceFlags |= SurfaceControl.OPAQUE; 459552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } else { 460552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mSurfaceFlags &= ~SurfaceControl.OPAQUE; 461552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 462552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 463552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 464d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private Rect getParentSurfaceInsets() { 465d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final ViewRootImpl root = getViewRootImpl(); 466d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (root == null) { 467d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr return null; 468d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } else { 469d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr return root.mWindowAttributes.surfaceInsets; 470d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 4713896db14751f16f4053e8fa4a82c3d6803054e5bJeff Tinker } 4723896db14751f16f4053e8fa4a82c3d6803054e5bJeff Tinker 4739a22f0f0a631849d9c622c642d3ab0395f77584bYoungsang Cho /** @hide */ 474d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr protected void updateSurface() { 47554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (!mHaveFrame) { 47654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return; 47754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 478a175a5b7ea3682cb58cca7f9726d0b8171cd549dJeff Brown ViewRootImpl viewRoot = getViewRootImpl(); 479d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) { 480d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr return; 481168173a698e820ceb1ebf54b4910888891be2056Joe Onorato } 48264f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima 483d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mTranslator = viewRoot.mTranslator; 4845be8de3420ba4c9d816b98e29bdec11715f6b626Dianne Hackborn if (mTranslator != null) { 4855be8de3420ba4c9d816b98e29bdec11715f6b626Dianne Hackborn mSurface.setCompatibilityTranslator(mTranslator); 48638ed7d7701514ee7127d0430e952930854608c4fMitsuru Oshima } 487a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 48854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int myWidth = mRequestedWidth; 48954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (myWidth <= 0) myWidth = getWidth(); 49054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project int myHeight = mRequestedHeight; 49154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (myHeight <= 0) myHeight = getHeight(); 492001a6e52445b2744b4f2eb00099b98a17f4245c9Mitsuru Oshima 49354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final boolean formatChanged = mFormat != mRequestedFormat; 494f0d3d3c06dd71453457035914a41872421f2932dRobert Carr final boolean visibleChanged = mVisible != mRequestedVisible; 495f0d3d3c06dd71453457035914a41872421f2932dRobert Carr final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged) 496d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr && mRequestedVisible; 497d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; 498d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; 49949b593efae85bc56381a68bd561a45d05b449796Robert Carr boolean redrawNeeded = false; 50049b593efae85bc56381a68bd561a45d05b449796Robert Carr 501d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) { 502f648108f83d4e74811919e9811efb8fcc184b8a3John Reck getLocationInWindow(mLocation); 503f648108f83d4e74811919e9811efb8fcc184b8a3John Reck 504aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 505aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "Changes: creating=" + creating 50654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project + " format=" + formatChanged + " size=" + sizeChanged 50754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project + " visible=" + visibleChanged 50864aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr + " left=" + (mWindowSpaceLeft != mLocation[0]) 50964aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr + " top=" + (mWindowSpaceTop != mLocation[1])); 51064f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima 51154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project try { 51254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project final boolean visible = mVisible = mRequestedVisible; 51364aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr mWindowSpaceLeft = mLocation[0]; 51464aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr mWindowSpaceTop = mLocation[1]; 515d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceWidth = myWidth; 516d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceHeight = myHeight; 51754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mFormat = mRequestedFormat; 518d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mLastWindowVisibility = mWindowVisibility; 51954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 520d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.left = mWindowSpaceLeft; 521d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.top = mWindowSpaceTop; 522d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.right = mWindowSpaceLeft + getWidth(); 523d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.bottom = mWindowSpaceTop + getHeight(); 52464f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima if (mTranslator != null) { 525d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mTranslator.translateRectInAppWindowToScreen(mScreenRect); 52664f59342d41849bd365cb43fad7505d5e3daa417Mitsuru Oshima } 527a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 528d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final Rect surfaceInsets = getParentSurfaceInsets(); 529d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.offset(surfaceInsets.left, surfaceInsets.top); 53064aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr 531d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (creating) { 532d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceSession = new SurfaceSession(viewRoot.mSurface); 5333bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr mDeferredDestroySurfaceControl = mSurfaceControl; 534552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 535552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr updateOpaqueFlag(); 536552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession, 537d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr "SurfaceView - " + viewRoot.getTitle().toString(), 538d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceWidth, mSurfaceHeight, mFormat, 539d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFlags); 54044ab5750929fe70da87ea82f0f914845f8141e08Robert Carr } else if (mSurfaceControl == null) { 54144ab5750929fe70da87ea82f0f914845f8141e08Robert Carr return; 5423896db14751f16f4053e8fa4a82c3d6803054e5bJeff Tinker } 5433896db14751f16f4053e8fa4a82c3d6803054e5bJeff Tinker 544d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr boolean realSizeChanged = false; 5456d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn 546726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mSurfaceLock.lock(); 547726426ee736929e605742bfa52bca4b20095921dDianne Hackborn try { 548726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mDrawingStopped = !visible; 549a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 550aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 551aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "Cur surface: " + mSurface); 5526d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn 553d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceControl.openTransaction(); 554d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr try { 555d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setLayer(mSubLayer); 556d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mViewVisibility) { 557d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.show(); 558d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } else { 559d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.hide(); 560d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 561d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 562d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // While creating the surface, we will set it's initial 563d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // geometry. Outside of that though, we should generally 564d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // leave it to the RenderThread. 565511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr // 566511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr // There is one more case when the buffer size changes we aren't yet 567511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr // prepared to sync (as even following the transaction applying 568511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr // we still need to latch a buffer). 569511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr // b/28866173 570511719f567bb124c27b21ca2f76697abe30ac70dRobert Carr if (sizeChanged || creating || !mRtHandlingPositionUpdates) { 571d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top); 572d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth, 573d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 0.0f, 0.0f, 574d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.height() / (float) mSurfaceHeight); 575d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 576d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (sizeChanged) { 577d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight); 578d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 579d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } finally { 580d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceControl.closeTransaction(); 581726426ee736929e605742bfa52bca4b20095921dDianne Hackborn } 5826d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn 583d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (sizeChanged || creating) { 584d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr redrawNeeded = true; 585d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 5866d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn 587726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mSurfaceFrame.left = 0; 588726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mSurfaceFrame.top = 0; 589726426ee736929e605742bfa52bca4b20095921dDianne Hackborn if (mTranslator == null) { 590d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFrame.right = mSurfaceWidth; 591d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFrame.bottom = mSurfaceHeight; 592726426ee736929e605742bfa52bca4b20095921dDianne Hackborn } else { 593726426ee736929e605742bfa52bca4b20095921dDianne Hackborn float appInvertedScale = mTranslator.applicationInvertedScale; 594d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); 595d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); 596726426ee736929e605742bfa52bca4b20095921dDianne Hackborn } 597a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 598726426ee736929e605742bfa52bca4b20095921dDianne Hackborn final int surfaceWidth = mSurfaceFrame.right; 599726426ee736929e605742bfa52bca4b20095921dDianne Hackborn final int surfaceHeight = mSurfaceFrame.bottom; 600726426ee736929e605742bfa52bca4b20095921dDianne Hackborn realSizeChanged = mLastSurfaceWidth != surfaceWidth 601726426ee736929e605742bfa52bca4b20095921dDianne Hackborn || mLastSurfaceHeight != surfaceHeight; 602726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mLastSurfaceWidth = surfaceWidth; 603726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mLastSurfaceHeight = surfaceHeight; 604726426ee736929e605742bfa52bca4b20095921dDianne Hackborn } finally { 605726426ee736929e605742bfa52bca4b20095921dDianne Hackborn mSurfaceLock.unlock(); 606589cebe2d58591403de4a77077941c0454bc91bcMitsuru Oshima } 60754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 60854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project try { 609d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr redrawNeeded |= visible && !mDrawFinished; 610d76b67c340d1564abf8d14d976fdaf83bf2b3320Dianne Hackborn 6116d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn SurfaceHolder.Callback callbacks[] = null; 61254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 613d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final boolean surfaceChanged = creating; 6146d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { 6156d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn mSurfaceCreated = false; 6166d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (mSurface.isValid()) { 617aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 618aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "visibleChanged -- surfaceDestroyed"); 6196d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn callbacks = getSurfaceCallbacks(); 6206d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn for (SurfaceHolder.Callback c : callbacks) { 6216d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn c.surfaceDestroyed(mSurfaceHolder); 6226d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn } 623387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // Since Android N the same surface may be reused and given to us 624387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // again by the system server at a later point. However 625387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // as we didn't do this in previous releases, clients weren't 626387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // necessarily required to clean up properly in 627387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // surfaceDestroyed. This leads to problems for example when 628387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // clients don't destroy their EGL context, and try 629387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // and create a new one on the same surface following reuse. 630387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // Since there is no valid use of the surface in-between 631387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // surfaceDestroyed and surfaceCreated, we force a disconnect, 632387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // so the next connect will always work if we end up reusing 633387838be955a44422509c2c7bc124327e9fe61d7Robert Carr // the surface. 6346ba466ff3e8565ca412c1e36dcb31a617fc42f6aJohn Reck if (mSurface.isValid()) { 6356ba466ff3e8565ca412c1e36dcb31a617fc42f6aJohn Reck mSurface.forceScopedDisconnect(); 6366ba466ff3e8565ca412c1e36dcb31a617fc42f6aJohn Reck } 6373d91492d694cf00474fec792134e496be6ee0313Mitsuru Oshima } 6386d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn } 6396d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn 640d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (creating) { 641d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurface.copyFrom(mSurfaceControl); 642d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 643d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 644453fc364c3ef49f0a965b0df2c64a6d42b9dca9fBryce Lee if (sizeChanged && getContext().getApplicationInfo().targetSdkVersion 64502949f14151f10f906f1fab58e788fadb98baba8Bryce Lee < Build.VERSION_CODES.O) { 64602949f14151f10f906f1fab58e788fadb98baba8Bryce Lee // Some legacy applications use the underlying native {@link Surface} object 64702949f14151f10f906f1fab58e788fadb98baba8Bryce Lee // as a key to whether anything has changed. In these cases, updates to the 64802949f14151f10f906f1fab58e788fadb98baba8Bryce Lee // existing {@link Surface} will be ignored when the size changes. 64902949f14151f10f906f1fab58e788fadb98baba8Bryce Lee // Therefore, we must explicitly recreate the {@link Surface} in these 65002949f14151f10f906f1fab58e788fadb98baba8Bryce Lee // cases. 65102949f14151f10f906f1fab58e788fadb98baba8Bryce Lee mSurface.createFrom(mSurfaceControl); 65202949f14151f10f906f1fab58e788fadb98baba8Bryce Lee } 65302949f14151f10f906f1fab58e788fadb98baba8Bryce Lee 654f750b8ce3c8cb30bcbc5fe53087c7e9035078ebaAndreas Röhl if (visible && mSurface.isValid()) { 6556d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { 6566d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn mSurfaceCreated = true; 65754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mIsCreating = true; 658aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 659aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "visibleChanged -- surfaceCreated"); 6606d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (callbacks == null) { 6616d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn callbacks = getSurfaceCallbacks(); 6626d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn } 66354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project for (SurfaceHolder.Callback c : callbacks) { 66454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project c.surfaceCreated(mSurfaceHolder); 66554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 66654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 66754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (creating || formatChanged || sizeChanged 668726426ee736929e605742bfa52bca4b20095921dDianne Hackborn || visibleChanged || realSizeChanged) { 669aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 670aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "surfaceChanged -- format=" + mFormat 6716d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn + " w=" + myWidth + " h=" + myHeight); 6726d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (callbacks == null) { 6736d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn callbacks = getSurfaceCallbacks(); 6746d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn } 675251fd430c7e355ad440202c83b0c6d91f5bf93e5Dianne Hackborn for (SurfaceHolder.Callback c : callbacks) { 676251fd430c7e355ad440202c83b0c6d91f5bf93e5Dianne Hackborn c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight); 677251fd430c7e355ad440202c83b0c6d91f5bf93e5Dianne Hackborn } 678d76b67c340d1564abf8d14d976fdaf83bf2b3320Dianne Hackborn } 679d76b67c340d1564abf8d14d976fdaf83bf2b3320Dianne Hackborn if (redrawNeeded) { 680aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " 681aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck + "surfaceRedrawNeeded"); 6826d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (callbacks == null) { 6836d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn callbacks = getSurfaceCallbacks(); 6846d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn } 6858508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr 6868508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr mPendingReportDraws++; 6878508bb2f10f8da49fff402d04ee81b2fba15ad19Robert Carr viewRoot.drawPending(); 68825cfa134835e3791bdb6572f5e25cf4599015678Robert Carr SurfaceCallbackHelper sch = 689d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr new SurfaceCallbackHelper(this::onDrawFinished); 69025cfa134835e3791bdb6572f5e25cf4599015678Robert Carr sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks); 69154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 69254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 69354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } finally { 69454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mIsCreating = false; 695d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mSurfaceControl != null && !mSurfaceCreated) { 696de84443489e95f1b406e3ba8d9e864d8b0adf061Robert Carr mSurface.release(); 69773678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr // If we are not in the stopped state, then the destruction of the Surface 69873678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr // represents a visual change we need to display, and we should go ahead 69973678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr // and destroy the SurfaceControl. However if we are in the stopped state, 70073678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr // we can just leave the Surface around so it can be a part of animations, 70173678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr // and we let the life-time be tied to the parent surface. 70273678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr if (!mWindowStopped) { 70373678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr mSurfaceControl.destroy(); 70473678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr mSurfaceControl = null; 70573678099f8f7886c97fb6ad4a0bfc307bed9ecf3Robert Carr } 706d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 70754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 708d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } catch (Exception ex) { 70944ab5750929fe70da87ea82f0f914845f8141e08Robert Carr Log.e(TAG, "Exception configuring surface", ex); 71054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 7116d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn if (DEBUG) Log.v( 712d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top 713d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr + " w=" + mScreenRect.width() + " h=" + mScreenRect.height() 714d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr + ", frame=" + mSurfaceFrame); 715f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck } else { 716f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // Calculate the window position in case RT loses the window 717f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // and we need to fallback to a UI-thread driven position update 718d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr getLocationInSurface(mLocation); 719f648108f83d4e74811919e9811efb8fcc184b8a3John Reck final boolean positionChanged = mWindowSpaceLeft != mLocation[0] 720f648108f83d4e74811919e9811efb8fcc184b8a3John Reck || mWindowSpaceTop != mLocation[1]; 721d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr final boolean layoutSizeChanged = getWidth() != mScreenRect.width() 722d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr || getHeight() != mScreenRect.height(); 723f648108f83d4e74811919e9811efb8fcc184b8a3John Reck if (positionChanged || layoutSizeChanged) { // Only the position has changed 724f648108f83d4e74811919e9811efb8fcc184b8a3John Reck mWindowSpaceLeft = mLocation[0]; 725f648108f83d4e74811919e9811efb8fcc184b8a3John Reck mWindowSpaceTop = mLocation[1]; 726d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // For our size changed check, we keep mScreenRect.width() and mScreenRect.height() 727f648108f83d4e74811919e9811efb8fcc184b8a3John Reck // in view local space. 728d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mLocation[0] = getWidth(); 729d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mLocation[1] = getHeight(); 73064aadd08491172e90f6d6512d8affc9a4cfa04ccRobert Carr 731d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop, 732f057fb56f69f8cb1bdee086c73f9d4efe8e331c4John Reck mLocation[0], mLocation[1]); 733f057fb56f69f8cb1bdee086c73f9d4efe8e331c4John Reck 734f057fb56f69f8cb1bdee086c73f9d4efe8e331c4John Reck if (mTranslator != null) { 735d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mTranslator.translateRectInAppWindowToScreen(mScreenRect); 736f057fb56f69f8cb1bdee086c73f9d4efe8e331c4John Reck } 737f057fb56f69f8cb1bdee086c73f9d4efe8e331c4John Reck 7383651ab8e097e2c5abcd55dde6005ec0c196c62f6Robert Carr if (mSurfaceControl == null) { 7393651ab8e097e2c5abcd55dde6005ec0c196c62f6Robert Carr return; 7403651ab8e097e2c5abcd55dde6005ec0c196c62f6Robert Carr } 7413651ab8e097e2c5abcd55dde6005ec0c196c62f6Robert Carr 74216e5089eb5b58fb065ec05ee8a6afe229f48bf50Bryce Lee if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) { 743f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck try { 744d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " + 745f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck "postion = [%d, %d, %d, %d]", System.identityHashCode(this), 746d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.left, mScreenRect.top, 747d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.right, mScreenRect.bottom)); 748d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr setParentSpaceRectangle(mScreenRect, -1); 749d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } catch (Exception ex) { 75044ab5750929fe70da87ea82f0f914845f8141e08Robert Carr Log.e(TAG, "Exception configuring surface", ex); 751f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck } 752f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 753f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 754f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 755f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 756f648108f83d4e74811919e9811efb8fcc184b8a3John Reck 757d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private void onDrawFinished() { 758d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (DEBUG) { 759d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr Log.i(TAG, System.identityHashCode(this) + " " 760d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr + "finishedDrawing"); 761d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 7623bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr 7633bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr if (mDeferredDestroySurfaceControl != null) { 7643bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr mDeferredDestroySurfaceControl.destroy(); 7653bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr mDeferredDestroySurfaceControl = null; 7663bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr } 7673bc95b5b712c44c687ef04156b63c70c930f69f2Robert Carr 7687992500d540e5411017d90da3ee4b02bbe283906John Reck runOnUiThread(() -> { 769b53670aecf2699022dffbf9400267ccf147eba64Robert Carr performDrawFinished(); 7707992500d540e5411017d90da3ee4b02bbe283906John Reck }); 771d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 772d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 773d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private void setParentSpaceRectangle(Rect position, long frameNumber) { 774d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr ViewRootImpl viewRoot = getViewRootImpl(); 775d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 776d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceControl.openTransaction(); 777d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr try { 778d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (frameNumber > 0) { 779d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber); 780d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 781d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setPosition(position.left, position.top); 782d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth, 783d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 0.0f, 0.0f, 784d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr position.height() / (float) mSurfaceHeight); 785d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } finally { 786d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr SurfaceControl.closeTransaction(); 787d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 788d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } 789d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 790f648108f83d4e74811919e9811efb8fcc184b8a3John Reck private Rect mRTLastReportedPosition = new Rect(); 791f648108f83d4e74811919e9811efb8fcc184b8a3John Reck 792f648108f83d4e74811919e9811efb8fcc184b8a3John Reck /** 7933387913237b1f73a775d10e83e1feb8a9b5d1831Robert Carr * Called by native by a Rendering Worker thread to update the window position 794f648108f83d4e74811919e9811efb8fcc184b8a3John Reck * @hide 795f648108f83d4e74811919e9811efb8fcc184b8a3John Reck */ 796d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr public final void updateSurfacePosition_renderWorker(long frameNumber, 797f648108f83d4e74811919e9811efb8fcc184b8a3John Reck int left, int top, int right, int bottom) { 798d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mSurfaceControl == null) { 799f648108f83d4e74811919e9811efb8fcc184b8a3John Reck return; 800f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 801d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr 802f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // TODO: This is teensy bit racey in that a brand new SurfaceView moving on 803f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // its 2nd frame if RenderThread is running slowly could potentially see 804f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // this as false, enter the branch, get pre-empted, then this comes along 805f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // and reports a new position, then the UI thread resumes and reports 806f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // its position. This could therefore be de-sync'd in that interval, but 807f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // the synchronization would violate the rule that RT must never block 808f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // on the UI thread which would open up potential deadlocks. The risk of 809f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // a single-frame desync is therefore preferable for now. 810f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck mRtHandlingPositionUpdates = true; 811f648108f83d4e74811919e9811efb8fcc184b8a3John Reck if (mRTLastReportedPosition.left == left 812f648108f83d4e74811919e9811efb8fcc184b8a3John Reck && mRTLastReportedPosition.top == top 813f648108f83d4e74811919e9811efb8fcc184b8a3John Reck && mRTLastReportedPosition.right == right 814f648108f83d4e74811919e9811efb8fcc184b8a3John Reck && mRTLastReportedPosition.bottom == bottom) { 815f648108f83d4e74811919e9811efb8fcc184b8a3John Reck return; 816f648108f83d4e74811919e9811efb8fcc184b8a3John Reck } 817f648108f83d4e74811919e9811efb8fcc184b8a3John Reck try { 818f648108f83d4e74811919e9811efb8fcc184b8a3John Reck if (DEBUG) { 819d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " + 820aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck "postion = [%d, %d, %d, %d]", System.identityHashCode(this), 821aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck frameNumber, left, top, right, bottom)); 82264e516f5fa56d71bf6b5076e5620c30dc5810ba1Rob Carr } 8235aec7b90310ba05f9816fd89030ba41ce48c568eWonsik Kim mRTLastReportedPosition.set(left, top, right, bottom); 824d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr setParentSpaceRectangle(mRTLastReportedPosition, frameNumber); 825d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr // Now overwrite mRTLastReportedPosition with our values 826d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } catch (Exception ex) { 827f648108f83d4e74811919e9811efb8fcc184b8a3John Reck Log.e(TAG, "Exception from repositionChild", ex); 82854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 82954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 83054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 831aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck /** 832d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr * Called by native on RenderThread to notify that the view is no longer in the 8333387913237b1f73a775d10e83e1feb8a9b5d1831Robert Carr * draw tree. UI thread is blocked at this point. 834aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck * @hide 835aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck */ 836d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr public final void surfacePositionLost_uiRtSync(long frameNumber) { 837aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) { 8383387913237b1f73a775d10e83e1feb8a9b5d1831Robert Carr Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d", 839aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck System.identityHashCode(this), frameNumber)); 840aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck } 841ad3a49310634f9befe8e7b1a057691ece1685a59Robert Carr mRTLastReportedPosition.setEmpty(); 842ad3a49310634f9befe8e7b1a057691ece1685a59Robert Carr 843d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mSurfaceControl == null) { 844474659ccc421aaacfa49a742891aefed46c6f5d2John Reck return; 845474659ccc421aaacfa49a742891aefed46c6f5d2John Reck } 846f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck if (mRtHandlingPositionUpdates) { 847f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck mRtHandlingPositionUpdates = false; 848f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // This callback will happen while the UI thread is blocked, so we can 849f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // safely access other member variables at this time. 850f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // So do what the UI thread would have done if RT wasn't handling position 851f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck // updates. 852d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) { 853f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck try { 854d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " + 855f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck "postion = [%d, %d, %d, %d]", System.identityHashCode(this), 856d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.left, mScreenRect.top, 857d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr mScreenRect.right, mScreenRect.bottom)); 858d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr setParentSpaceRectangle(mScreenRect, frameNumber); 859d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr } catch (Exception ex) { 86044ab5750929fe70da87ea82f0f914845f8141e08Robert Carr Log.e(TAG, "Exception configuring surface", ex); 861f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck } 862f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck } 863f23a1b8e4c5e63d11fe12fb1d51e4f5e3570bbc2John Reck } 864aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck } 865aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck 8666d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn private SurfaceHolder.Callback[] getSurfaceCallbacks() { 8676d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn SurfaceHolder.Callback callbacks[]; 8686d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn synchronized (mCallbacks) { 8696d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn callbacks = new SurfaceHolder.Callback[mCallbacks.size()]; 8706d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn mCallbacks.toArray(callbacks); 87154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 8726d05fd3c795088ac60f86382df5a66d631e8a0cbDianne Hackborn return callbacks; 87354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 87454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 8757179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger /** 8763b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa * This method still exists only for compatibility reasons because some applications have relied 8773b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa * on this method via reflection. See Issue 36345857 for details. 8783b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa * 8793b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa * @deprecated No platform code is using this method anymore. 8803b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa * @hide 8813b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa */ 8823b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa @Deprecated 8833b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa public void setWindowType(int type) { 884f383c24749ae6bfcf8f8cee26fe7bc6897f7511cJeff Sharkey if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) { 8853b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa throw new UnsupportedOperationException( 8863b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa "SurfaceView#setWindowType() has never been a public API."); 8873b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa } 8883b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa 8893b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa if (type == TYPE_APPLICATION_PANEL) { 8903b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa Log.e(TAG, "If you are calling SurfaceView#setWindowType(TYPE_APPLICATION_PANEL) " 8913b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa + "just to make the SurfaceView to be placed on top of its window, you must " 8923b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa + "call setZOrderOnTop(true) instead.", new Throwable()); 8933b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa setZOrderOnTop(true); 8943b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa return; 8953b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa } 8963b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa Log.e(TAG, "SurfaceView#setWindowType(int) is deprecated and now does nothing. " 8973b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa + "type=" + type, new Throwable()); 8983b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa } 8993b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa 9007992500d540e5411017d90da3ee4b02bbe283906John Reck private void runOnUiThread(Runnable runnable) { 9017992500d540e5411017d90da3ee4b02bbe283906John Reck Handler handler = getHandler(); 9027992500d540e5411017d90da3ee4b02bbe283906John Reck if (handler != null && handler.getLooper() != Looper.myLooper()) { 9037992500d540e5411017d90da3ee4b02bbe283906John Reck handler.post(runnable); 9047992500d540e5411017d90da3ee4b02bbe283906John Reck } else { 9057992500d540e5411017d90da3ee4b02bbe283906John Reck runnable.run(); 9067992500d540e5411017d90da3ee4b02bbe283906John Reck } 9077992500d540e5411017d90da3ee4b02bbe283906John Reck } 9087992500d540e5411017d90da3ee4b02bbe283906John Reck 9093b5011afc9e17963607269bfb6665d04e3ab4ca1Yohei Yukawa /** 9107179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger * Check to see if the surface has fixed size dimensions or if the surface's 9117179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger * dimensions are dimensions are dependent on its current layout. 9127179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger * 9137179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger * @return true if the surface has dimensions that are fixed in size 9147179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger * @hide 9157179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger */ 9167179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger public boolean isFixedSize() { 9177179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger return (mRequestedWidth != -1 || mRequestedHeight != -1); 9187179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger } 9197179b8133d4a1d8e5f26cbe3da6aa978094e75c9Derek Sollenberger 920d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr private boolean isAboveParent() { 921d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr return mSubLayer >= 0; 92254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 92354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 924a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() { 92554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project private static final String LOG_TAG = "SurfaceHolder"; 926a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 927a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 92854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public boolean isCreating() { 92954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return mIsCreating; 93054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 93154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 932a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 93354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void addCallback(Callback callback) { 93454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project synchronized (mCallbacks) { 935a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin // This is a linear search, but in practice we'll 93654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // have only a couple callbacks, so it doesn't matter. 937a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin if (mCallbacks.contains(callback) == false) { 93854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mCallbacks.add(callback); 93954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 94054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 94154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 94254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 943a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 94454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void removeCallback(Callback callback) { 94554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project synchronized (mCallbacks) { 94654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mCallbacks.remove(callback); 94754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 94854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 949a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 950a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 95154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setFixedSize(int width, int height) { 95254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (mRequestedWidth != width || mRequestedHeight != height) { 95354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mRequestedWidth = width; 95454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mRequestedHeight = height; 95554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project requestLayout(); 95654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 95754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 95854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 959a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 96054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setSizeFromLayout() { 96154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (mRequestedWidth != -1 || mRequestedHeight != -1) { 96254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mRequestedWidth = mRequestedHeight = -1; 96354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project requestLayout(); 96454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 96554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 96654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 967a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 96854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setFormat(int format) { 9692d468c5d73cc1cefbcfa8d98e30622c54756918cMathias Agopian // for backward compatibility reason, OPAQUE always 9702d468c5d73cc1cefbcfa8d98e30622c54756918cMathias Agopian // means 565 for SurfaceView 9712d468c5d73cc1cefbcfa8d98e30622c54756918cMathias Agopian if (format == PixelFormat.OPAQUE) 9722d468c5d73cc1cefbcfa8d98e30622c54756918cMathias Agopian format = PixelFormat.RGB_565; 9732d468c5d73cc1cefbcfa8d98e30622c54756918cMathias Agopian 97454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mRequestedFormat = format; 975d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (mSurfaceControl != null) { 976d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr updateSurface(); 97754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 97854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 97954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 980d2112306330ce0c162bee4b864991962ca2b655aMathias Agopian /** 981d2112306330ce0c162bee4b864991962ca2b655aMathias Agopian * @deprecated setType is now ignored. 982d2112306330ce0c162bee4b864991962ca2b655aMathias Agopian */ 983a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 984d2112306330ce0c162bee4b864991962ca2b655aMathias Agopian @Deprecated 985d2112306330ce0c162bee4b864991962ca2b655aMathias Agopian public void setType(int type) { } 98654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 987a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 98854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void setKeepScreenOn(boolean screenOn) { 9897992500d540e5411017d90da3ee4b02bbe283906John Reck runOnUiThread(() -> SurfaceView.this.setKeepScreenOn(screenOn)); 99054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 991a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 9929ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian /** 9939ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * Gets a {@link Canvas} for drawing into the SurfaceView's Surface 9949ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * 9959ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * After drawing into the provided {@link Canvas}, the caller must 9969ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. 9979ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * 9989ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * The caller must redraw the entire surface. 9999ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * @return A canvas for drawing into the surface. 10009ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian */ 1001a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 100254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public Canvas lockCanvas() { 10036bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck return internalLockCanvas(null, false); 100454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 100554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 10069ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian /** 10079ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * Gets a {@link Canvas} for drawing into the SurfaceView's Surface 10089ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * 10099ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * After drawing into the provided {@link Canvas}, the caller must 10109ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. 10119ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * 10129ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * @param inOutDirty A rectangle that represents the dirty region that the caller wants 10139ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * to redraw. This function may choose to expand the dirty rectangle if for example 10149ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * the surface has been resized or if the previous contents of the surface were 10159ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * not available. The caller must redraw the entire dirty region as represented 10169ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * by the contents of the inOutDirty rectangle upon return from this function. 10179ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * The caller may also pass <code>null</code> instead, in the case where the 10189ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * entire surface should be redrawn. 10199ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * @return A canvas for drawing into the surface. 10209ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian */ 1021a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 10229ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian public Canvas lockCanvas(Rect inOutDirty) { 10236bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck return internalLockCanvas(inOutDirty, false); 102454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 102554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 10266bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck @Override 10276bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck public Canvas lockHardwareCanvas() { 10286bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck return internalLockCanvas(null, true); 10296bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck } 10306bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck 10316bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck private Canvas internalLockCanvas(Rect dirty, boolean hardware) { 103254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mSurfaceLock.lock(); 103354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1034aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped=" 1035d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr + mDrawingStopped + ", surfaceControl=" + mSurfaceControl); 103654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 103754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project Canvas c = null; 1038d5c7dd6da810a6b89151b337bea79fd817e6b72aRobert Carr if (!mDrawingStopped && mSurfaceControl != null) { 103954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project try { 10406bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck if (hardware) { 10416bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck c = mSurface.lockHardwareCanvas(); 10426bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck } else { 10436bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck c = mSurface.lockCanvas(dirty); 10446bc701421047bf881ee16c49b242ea19ae4cd9b9John Reck } 104554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } catch (Exception e) { 104654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project Log.e(LOG_TAG, "Exception locking surface", e); 104754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 104854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 104954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1050aa6e84f21ddf89ea649a3f00044bc23adfe86978John Reck if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c); 105154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (c != null) { 105254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mLastLockTime = SystemClock.uptimeMillis(); 105354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return c; 105454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 1055a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 105654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // If the Surface is not ready to be drawn, then return null, 105754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // but throttle calls to this function so it isn't called more 105854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project // than every 100ms. 105954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project long now = SystemClock.uptimeMillis(); 106054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project long nextTime = mLastLockTime + 100; 106154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project if (nextTime > now) { 106254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project try { 106354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project Thread.sleep(nextTime-now); 106454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } catch (InterruptedException e) { 106554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 106654b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project now = SystemClock.uptimeMillis(); 106754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 106854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mLastLockTime = now; 106954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mSurfaceLock.unlock(); 1070a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin 107154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return null; 107254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 107354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 10749ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian /** 10759ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * Posts the new contents of the {@link Canvas} to the surface and 10769ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * releases the {@link Canvas}. 10779ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * 10789ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian * @param canvas The canvas previously obtained from {@link #lockCanvas}. 10799ddf32aa8ac5aa8c29a8063f0528838f1436e5ddMathias Agopian */ 1080a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 108154b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public void unlockCanvasAndPost(Canvas canvas) { 108254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mSurface.unlockCanvasAndPost(canvas); 108354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project mSurfaceLock.unlock(); 108454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 108554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1086a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 108754b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public Surface getSurface() { 108854b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return mSurface; 108954b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 109054b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project 1091a86ab640f7bb0bf3cb4eaed80473ca8c5d131903Igor Murashkin @Override 109254b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project public Rect getSurfaceFrame() { 109354b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project return mSurfaceFrame; 109454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project } 109554b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project }; 1096552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1097552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr class SurfaceControlWithBackground extends SurfaceControl { 1098552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr private SurfaceControl mBackgroundControl; 1099552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr private boolean mOpaque = true; 1100552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public boolean mVisible = false; 1101552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1102552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public SurfaceControlWithBackground(SurfaceSession s, 1103552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr String name, int w, int h, int format, int flags) 1104552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr throws Exception { 1105552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super(s, name, w, h, format, flags); 1106552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h, 1107552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM); 1108552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mOpaque = (flags & SurfaceControl.OPAQUE) != 0; 1109552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1110552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1111552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1112552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setAlpha(float alpha) { 1113552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setAlpha(alpha); 1114552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setAlpha(alpha); 1115552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1116552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1117552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1118552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setLayer(int zorder) { 1119552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setLayer(zorder); 1120552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr // -3 is below all other child layers as SurfaceView never goes below -2 1121552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setLayer(-3); 1122552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1123552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1124552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1125552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setPosition(float x, float y) { 1126552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setPosition(x, y); 1127552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setPosition(x, y); 1128552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1129552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1130552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1131552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setSize(int w, int h) { 1132552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setSize(w, h); 1133552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setSize(w, h); 1134552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1135552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1136552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1137552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setWindowCrop(Rect crop) { 1138552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setWindowCrop(crop); 1139552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setWindowCrop(crop); 1140552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1141552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1142552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1143552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setFinalCrop(Rect crop) { 1144552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setFinalCrop(crop); 1145552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setFinalCrop(crop); 1146552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1147552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1148552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1149552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setLayerStack(int layerStack) { 1150552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setLayerStack(layerStack); 1151552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setLayerStack(layerStack); 1152552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1153552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1154552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1155552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setOpaque(boolean isOpaque) { 1156552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setOpaque(isOpaque); 1157552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mOpaque = isOpaque; 1158552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr updateBackgroundVisibility(); 1159552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1160552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1161552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1162552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setSecure(boolean isSecure) { 1163552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setSecure(isSecure); 1164552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1165552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1166552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1167552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { 1168552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setMatrix(dsdx, dtdx, dsdy, dtdy); 1169552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy); 1170552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1171552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1172552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1173552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void hide() { 1174552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.hide(); 1175552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mVisible = false; 1176552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr updateBackgroundVisibility(); 1177552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1178552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1179552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1180552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void show() { 1181552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.show(); 1182552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mVisible = true; 1183552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr updateBackgroundVisibility(); 1184552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1185552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1186552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1187552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void destroy() { 1188552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.destroy(); 1189552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.destroy(); 1190552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1191552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1192552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1193552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void release() { 1194552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.release(); 1195552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.release(); 1196552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1197552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1198552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1199552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void setTransparentRegionHint(Region region) { 1200552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.setTransparentRegionHint(region); 1201552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.setTransparentRegionHint(region); 1202552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1203552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1204552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr @Override 1205552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr public void deferTransactionUntil(IBinder handle, long frame) { 1206552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr super.deferTransactionUntil(handle, frame); 1207552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.deferTransactionUntil(handle, frame); 1208552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1209552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr 1210552da0e0cdf40ae7849a86457072028a0d604724Robert Carr @Override 1211552da0e0cdf40ae7849a86457072028a0d604724Robert Carr public void deferTransactionUntil(Surface barrier, long frame) { 1212552da0e0cdf40ae7849a86457072028a0d604724Robert Carr super.deferTransactionUntil(barrier, frame); 1213552da0e0cdf40ae7849a86457072028a0d604724Robert Carr mBackgroundControl.deferTransactionUntil(barrier, frame); 1214552da0e0cdf40ae7849a86457072028a0d604724Robert Carr } 1215552da0e0cdf40ae7849a86457072028a0d604724Robert Carr 1216552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr void updateBackgroundVisibility() { 1217552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr if (mOpaque && mVisible) { 1218552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.show(); 1219552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } else { 1220552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr mBackgroundControl.hide(); 1221552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1222552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 1223552355529335c0c3593b0f79f54d84a90b93a62cRobert Carr } 122454b6cfa9a9e5b861a9930af873580d6dc20f773The Android Open Source Project} 1225