blob: 462dad3fad7ad54a5ec523f0a4833984565c3e77 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
Yohei Yukawa9309c192017-09-09 17:45:27 -070019import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
Robert Carrd5c7dd62017-03-08 10:39:30 -080020import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
Yohei Yukawa3b5011a2017-03-16 15:34:12 -070021import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
Robert Carrd5c7dd62017-03-08 10:39:30 -080022import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
23
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070024import android.content.Context;
Mitsuru Oshima64f59342009-06-21 00:03:11 -070025import android.content.res.CompatibilityInfo.Translator;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070026import android.content.res.Configuration;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070027import android.graphics.Canvas;
28import android.graphics.PixelFormat;
29import android.graphics.PorterDuff;
30import android.graphics.Rect;
31import android.graphics.Region;
Yohei Yukawa3b5011a2017-03-16 15:34:12 -070032import android.os.Build;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070033import android.os.Handler;
Robert Carr55235552017-06-02 14:21:03 -070034import android.os.IBinder;
John Reck79925002017-05-26 13:57:14 -070035import android.os.Looper;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070036import android.os.SystemClock;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070037import android.util.AttributeSet;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070038import android.util.Log;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070039
Robert Carr25cfa132016-11-16 13:24:09 -080040import com.android.internal.view.SurfaceCallbackHelper;
Aurimas Liutikas67e2ae82016-10-11 18:17:42 -070041
Jon Larimer9bdf5762009-01-02 18:55:15 -050042import java.util.ArrayList;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070043import java.util.concurrent.locks.ReentrantLock;
44
45/**
46 * Provides a dedicated drawing surface embedded inside of a view hierarchy.
47 * You can control the format of this surface and, if you like, its size; the
48 * SurfaceView takes care of placing the surface at the correct location on the
49 * screen
Igor Murashkina86ab6402013-08-30 12:58:36 -070050 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070051 * <p>The surface is Z ordered so that it is behind the window holding its
52 * SurfaceView; the SurfaceView punches a hole in its window to allow its
Jesse Hallc9f345f2012-09-26 11:55:16 -070053 * surface to be displayed. The view hierarchy will take care of correctly
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070054 * compositing with the Surface any siblings of the SurfaceView that would
Jesse Hallc9f345f2012-09-26 11:55:16 -070055 * normally appear on top of it. This can be used to place overlays such as
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070056 * buttons on top of the Surface, though note however that it can have an
57 * impact on performance since a full alpha-blended composite will be performed
58 * each time the Surface changes.
Igor Murashkina86ab6402013-08-30 12:58:36 -070059 *
Jesse Hallc9f345f2012-09-26 11:55:16 -070060 * <p> The transparent region that makes the surface visible is based on the
61 * layout positions in the view hierarchy. If the post-layout transform
62 * properties are used to draw a sibling view on top of the SurfaceView, the
63 * view may not be properly composited with the surface.
64 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070065 * <p>Access to the underlying surface is provided via the SurfaceHolder interface,
66 * which can be retrieved by calling {@link #getHolder}.
Igor Murashkina86ab6402013-08-30 12:58:36 -070067 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070068 * <p>The Surface will be created for you while the SurfaceView's window is
69 * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated}
70 * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the
71 * Surface is created and destroyed as the window is shown and hidden.
Igor Murashkina86ab6402013-08-30 12:58:36 -070072 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070073 * <p>One of the purposes of this class is to provide a surface in which a
Jesse Hallc9f345f2012-09-26 11:55:16 -070074 * secondary thread can render into the screen. If you are going to use it
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070075 * this way, you need to be aware of some threading semantics:
Igor Murashkina86ab6402013-08-30 12:58:36 -070076 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070077 * <ul>
78 * <li> All SurfaceView and
79 * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called
80 * from the thread running the SurfaceView's window (typically the main thread
Jesse Hallc9f345f2012-09-26 11:55:16 -070081 * of the application). They thus need to correctly synchronize with any
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070082 * state that is also touched by the drawing thread.
83 * <li> You must ensure that the drawing thread only touches the underlying
84 * Surface while it is valid -- between
85 * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()}
86 * and
87 * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}.
88 * </ul>
Chris Craik6ee192f2016-05-17 14:29:10 -070089 *
90 * <p class="note"><strong>Note:</strong> Starting in platform version
91 * {@link android.os.Build.VERSION_CODES#N}, SurfaceView's window position is
92 * updated synchronously with other View rendering. This means that translating
93 * and scaling a SurfaceView on screen will not cause rendering artifacts. Such
94 * artifacts may occur on previous versions of the platform when its window is
95 * positioned asynchronously.</p>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070096 */
Robert Carr414ebc62017-04-12 12:01:00 -070097public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
Robert Carrd5c7dd62017-03-08 10:39:30 -080098 private static final String TAG = "SurfaceView";
99 private static final boolean DEBUG = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700100
101 final ArrayList<SurfaceHolder.Callback> mCallbacks
102 = new ArrayList<SurfaceHolder.Callback>();
103
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800104 final int[] mLocation = new int[2];
Igor Murashkina86ab6402013-08-30 12:58:36 -0700105
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700106 final ReentrantLock mSurfaceLock = new ReentrantLock();
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800107 final Surface mSurface = new Surface(); // Current surface in use
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700108 boolean mDrawingStopped = true;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800109 // We use this to track if the application has produced a frame
110 // in to the Surface. Up until that point, we should be careful not to punch
111 // holes.
112 boolean mDrawFinished = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700113
Robert Carrd5c7dd62017-03-08 10:39:30 -0800114 final Rect mScreenRect = new Rect();
115 SurfaceSession mSurfaceSession;
116
117 SurfaceControl mSurfaceControl;
Robert Carr3bc95b52017-03-20 21:57:23 -0700118 // In the case of format changes we switch out the surface in-place
119 // we need to preserve the old one until the new one has drawn.
120 SurfaceControl mDeferredDestroySurfaceControl;
Robert Carr33879132016-09-06 14:41:40 -0700121 final Rect mTmpRect = new Rect();
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700122 final Configuration mConfiguration = new Configuration();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700123
Robert Carrd5c7dd62017-03-08 10:39:30 -0800124 int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700125
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700126 boolean mIsCreating = false;
John Reckf23a1b82016-06-22 14:23:31 -0700127 private volatile boolean mRtHandlingPositionUpdates = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700128
John Reckf6481082016-02-02 15:18:23 -0800129 private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700130 = new ViewTreeObserver.OnScrollChangedListener() {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700131 @Override
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700132 public void onScrollChanged() {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800133 updateSurface();
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700134 }
135 };
Igor Murashkina86ab6402013-08-30 12:58:36 -0700136
John Reckf6481082016-02-02 15:18:23 -0800137 private final ViewTreeObserver.OnPreDrawListener mDrawListener =
138 new ViewTreeObserver.OnPreDrawListener() {
139 @Override
140 public boolean onPreDraw() {
141 // reposition ourselves where the surface is
142 mHaveFrame = getWidth() > 0 && getHeight() > 0;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800143 updateSurface();
John Reckf6481082016-02-02 15:18:23 -0800144 return true;
145 }
146 };
147
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700148 boolean mRequestedVisible = false;
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700149 boolean mWindowVisibility = false;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800150 boolean mLastWindowVisibility = false;
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700151 boolean mViewVisibility = false;
Robert Carr414ebc62017-04-12 12:01:00 -0700152 boolean mWindowStopped = false;
153
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700154 int mRequestedWidth = -1;
155 int mRequestedHeight = -1;
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700156 /* Set SurfaceView's format to 565 by default to maintain backward
157 * compatibility with applications assuming this format.
158 */
159 int mRequestedFormat = PixelFormat.RGB_565;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700160
161 boolean mHaveFrame = false;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800162 boolean mSurfaceCreated = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700163 long mLastLockTime = 0;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700164
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700165 boolean mVisible = false;
Robert Carr64aadd02015-11-06 13:54:20 -0800166 int mWindowSpaceLeft = -1;
167 int mWindowSpaceTop = -1;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800168 int mSurfaceWidth = -1;
169 int mSurfaceHeight = -1;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700170 int mFormat = -1;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700171 final Rect mSurfaceFrame = new Rect();
Dianne Hackborn726426e2010-03-31 22:04:36 -0700172 int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700173 private Translator mTranslator;
Romain Guyf2499fa2011-01-26 18:31:23 -0800174
Romain Guy01d5edc2011-01-28 11:28:53 -0800175 private boolean mGlobalListenersAdded;
Robert Carr8508bb22017-03-27 15:46:27 -0700176 private boolean mAttachedToWindow;
Romain Guyf2499fa2011-01-26 18:31:23 -0800177
Robert Carrd5c7dd62017-03-08 10:39:30 -0800178 private int mSurfaceFlags = SurfaceControl.HIDDEN;
179
Robert Carr8508bb22017-03-27 15:46:27 -0700180 private int mPendingReportDraws;
181
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700182 public SurfaceView(Context context) {
Alan Viverette768ca7d2016-08-04 09:54:14 -0400183 this(context, null);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700184 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700185
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700186 public SurfaceView(Context context, AttributeSet attrs) {
Alan Viverette768ca7d2016-08-04 09:54:14 -0400187 this(context, attrs, 0);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700188 }
189
Alan Viverette617feb92013-09-09 18:09:13 -0700190 public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
Alan Viverette768ca7d2016-08-04 09:54:14 -0400191 this(context, attrs, defStyleAttr, 0);
Alan Viverette617feb92013-09-09 18:09:13 -0700192 }
193
194 public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
195 super(context, attrs, defStyleAttr, defStyleRes);
John Reck3acf03822016-11-02 11:14:47 -0700196 mRenderNode.requestPositionUpdates(this);
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700197
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700198 setWillNotDraw(true);
199 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700200
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700201 /**
202 * Return the SurfaceHolder providing access and control over this
203 * SurfaceView's underlying surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700204 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700205 * @return SurfaceHolder The holder of the surface.
206 */
207 public SurfaceHolder getHolder() {
208 return mSurfaceHolder;
209 }
210
Robert Carr414ebc62017-04-12 12:01:00 -0700211 private void updateRequestedVisibility() {
212 mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped;
213 }
214
215 /** @hide */
216 @Override
217 public void windowStopped(boolean stopped) {
218 mWindowStopped = stopped;
219 updateRequestedVisibility();
220 updateSurface();
221 }
222
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700223 @Override
224 protected void onAttachedToWindow() {
225 super.onAttachedToWindow();
Robert Carr414ebc62017-04-12 12:01:00 -0700226
227 getViewRootImpl().addWindowStoppedCallback(this);
Robert Carr00177cc2017-05-15 15:49:17 -0700228 mWindowStopped = false;
Robert Carr414ebc62017-04-12 12:01:00 -0700229
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700230 mViewVisibility = getVisibility() == VISIBLE;
Robert Carr414ebc62017-04-12 12:01:00 -0700231 updateRequestedVisibility();
Romain Guy01d5edc2011-01-28 11:28:53 -0800232
Robert Carr8508bb22017-03-27 15:46:27 -0700233 mAttachedToWindow = true;
Karthik Ravi Shankara59c3a52017-09-11 17:36:25 -0700234 mParent.requestTransparentRegion(SurfaceView.this);
Romain Guy01d5edc2011-01-28 11:28:53 -0800235 if (!mGlobalListenersAdded) {
236 ViewTreeObserver observer = getViewTreeObserver();
237 observer.addOnScrollChangedListener(mScrollChangedListener);
238 observer.addOnPreDrawListener(mDrawListener);
239 mGlobalListenersAdded = true;
240 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700241 }
242
243 @Override
244 protected void onWindowVisibilityChanged(int visibility) {
245 super.onWindowVisibilityChanged(visibility);
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700246 mWindowVisibility = visibility == VISIBLE;
Robert Carr414ebc62017-04-12 12:01:00 -0700247 updateRequestedVisibility();
Robert Carrd5c7dd62017-03-08 10:39:30 -0800248 updateSurface();
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700249 }
250
251 @Override
252 public void setVisibility(int visibility) {
253 super.setVisibility(visibility);
254 mViewVisibility = visibility == VISIBLE;
Robert Carr414ebc62017-04-12 12:01:00 -0700255 boolean newRequestedVisible = mWindowVisibility && mViewVisibility && !mWindowStopped;
Mathias Agopiancbeb3322012-05-12 19:57:07 -0700256 if (newRequestedVisible != mRequestedVisible) {
257 // our base class (View) invalidates the layout only when
258 // we go from/to the GONE state. However, SurfaceView needs
259 // to request a re-layout when the visibility changes at all.
260 // This is needed because the transparent region is computed
261 // as part of the layout phase, and it changes (obviously) when
262 // the visibility changes.
263 requestLayout();
264 }
265 mRequestedVisible = newRequestedVisible;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800266 updateSurface();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700267 }
Romain Guyafc3e112010-06-07 17:04:33 -0700268
Robert Carrb53670a2017-05-25 18:20:49 -0700269 private void performDrawFinished() {
270 if (mPendingReportDraws > 0) {
271 mDrawFinished = true;
272 if (mAttachedToWindow) {
Robert Carrb53670a2017-05-25 18:20:49 -0700273 notifyDrawFinished();
274 invalidate();
275 }
276 } else {
277 Log.e(TAG, System.identityHashCode(this) + "finished drawing"
278 + " but no pending report draw (extra call"
279 + " to draw completion runnable?)");
280 }
281 }
282
Robert Carr8508bb22017-03-27 15:46:27 -0700283 void notifyDrawFinished() {
284 ViewRootImpl viewRoot = getViewRootImpl();
285 if (viewRoot != null) {
286 viewRoot.pendingDrawFinished();
287 }
288 mPendingReportDraws--;
289 }
290
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700291 @Override
John Reck77e4a522014-10-01 10:38:07 -0700292 protected void onDetachedFromWindow() {
Lucas Dupin0c207342017-04-14 19:47:23 -0700293 ViewRootImpl viewRoot = getViewRootImpl();
294 // It's possible to create a SurfaceView using the default constructor and never
295 // attach it to a view hierarchy, this is a common use case when dealing with
296 // OpenGL. A developer will probably create a new GLSurfaceView, and let it manage
297 // the lifecycle. Instead of attaching it to a view, he/she can just pass
298 // the SurfaceHolder forward, most live wallpapers do it.
299 if (viewRoot != null) {
300 viewRoot.removeWindowStoppedCallback(this);
301 }
Robert Carr414ebc62017-04-12 12:01:00 -0700302
Robert Carr8508bb22017-03-27 15:46:27 -0700303 mAttachedToWindow = false;
Romain Guy01d5edc2011-01-28 11:28:53 -0800304 if (mGlobalListenersAdded) {
305 ViewTreeObserver observer = getViewTreeObserver();
306 observer.removeOnScrollChangedListener(mScrollChangedListener);
307 observer.removeOnPreDrawListener(mDrawListener);
308 mGlobalListenersAdded = false;
309 }
310
Robert Carr8508bb22017-03-27 15:46:27 -0700311 while (mPendingReportDraws > 0) {
312 notifyDrawFinished();
313 }
314
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700315 mRequestedVisible = false;
Wonsik Kim5aec7b92017-03-07 17:15:50 -0800316
Robert Carrd5c7dd62017-03-08 10:39:30 -0800317 updateSurface();
318 if (mSurfaceControl != null) {
319 mSurfaceControl.destroy();
320 }
321 mSurfaceControl = null;
322
323 mHaveFrame = false;
Robert Carr414ebc62017-04-12 12:01:00 -0700324
John Reck77e4a522014-10-01 10:38:07 -0700325 super.onDetachedFromWindow();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700326 }
327
328 @Override
329 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Dianne Hackborn189ee182010-12-02 21:48:53 -0800330 int width = mRequestedWidth >= 0
331 ? resolveSizeAndState(mRequestedWidth, widthMeasureSpec, 0)
332 : getDefaultSize(0, widthMeasureSpec);
333 int height = mRequestedHeight >= 0
334 ? resolveSizeAndState(mRequestedHeight, heightMeasureSpec, 0)
335 : getDefaultSize(0, heightMeasureSpec);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700336 setMeasuredDimension(width, height);
337 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700338
Mathias Agopianef115302010-10-04 20:15:08 -0700339 /** @hide */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700340 @Override
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700341 protected boolean setFrame(int left, int top, int right, int bottom) {
342 boolean result = super.setFrame(left, top, right, bottom);
Robert Carrd5c7dd62017-03-08 10:39:30 -0800343 updateSurface();
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700344 return result;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700345 }
346
347 @Override
348 public boolean gatherTransparentRegion(Region region) {
Robert Carr3ca12be72017-05-22 14:57:48 -0700349 if (isAboveParent() || !mDrawFinished) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700350 return super.gatherTransparentRegion(region);
351 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700352
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700353 boolean opaque = true;
Dianne Hackborn4702a852012-08-17 15:18:29 -0700354 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700355 // this view draws, remove it from the transparent region
356 opaque = super.gatherTransparentRegion(region);
357 } else if (region != null) {
358 int w = getWidth();
359 int h = getHeight();
360 if (w>0 && h>0) {
361 getLocationInWindow(mLocation);
362 // otherwise, punch a hole in the whole hierarchy
363 int l = mLocation[0];
364 int t = mLocation[1];
365 region.op(l, t, l+w, t+h, Region.Op.UNION);
366 }
367 }
368 if (PixelFormat.formatHasAlpha(mRequestedFormat)) {
369 opaque = false;
370 }
371 return opaque;
372 }
373
374 @Override
375 public void draw(Canvas canvas) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800376 if (mDrawFinished && !isAboveParent()) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700377 // draw() is not called when SKIP_DRAW is set
Dianne Hackborn4702a852012-08-17 15:18:29 -0700378 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700379 // punch a whole in the view-hierarchy below us
380 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
381 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700382 }
383 super.draw(canvas);
384 }
385
386 @Override
387 protected void dispatchDraw(Canvas canvas) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800388 if (mDrawFinished && !isAboveParent()) {
389 // draw() is not called when SKIP_DRAW is set
Dianne Hackborn4702a852012-08-17 15:18:29 -0700390 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700391 // punch a whole in the view-hierarchy below us
392 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
393 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700394 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700395 super.dispatchDraw(canvas);
396 }
397
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700398 /**
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700399 * Control whether the surface view's surface is placed on top of another
400 * regular surface view in the window (but still behind the window itself).
401 * This is typically used to place overlays on top of an underlying media
402 * surface view.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700403 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700404 * <p>Note that this must be set before the surface view's containing
405 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700406 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700407 * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
408 */
409 public void setZOrderMediaOverlay(boolean isMediaOverlay) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800410 mSubLayer = isMediaOverlay
411 ? APPLICATION_MEDIA_OVERLAY_SUBLAYER : APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700412 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700413
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700414 /**
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700415 * Control whether the surface view's surface is placed on top of its
416 * window. Normally it is placed behind the window, to allow it to
417 * (for the most part) appear to composite with the views in the
418 * hierarchy. By setting this, you cause it to be placed above the
419 * window. This means that none of the contents of the window this
420 * SurfaceView is in will be visible on top of its surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700421 *
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700422 * <p>Note that this must be set before the surface view's containing
423 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700424 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700425 * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700426 */
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700427 public void setZOrderOnTop(boolean onTop) {
Derek Sollenbergerecde72f2010-03-01 13:44:42 -0500428 if (onTop) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800429 mSubLayer = APPLICATION_PANEL_SUBLAYER;
Derek Sollenbergerecde72f2010-03-01 13:44:42 -0500430 } else {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800431 mSubLayer = APPLICATION_MEDIA_SUBLAYER;
Derek Sollenbergerecde72f2010-03-01 13:44:42 -0500432 }
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700433 }
Jeff Brownf0681b32012-10-23 17:35:57 -0700434
435 /**
436 * Control whether the surface view's content should be treated as secure,
437 * preventing it from appearing in screenshots or from being viewed on
438 * non-secure displays.
439 *
440 * <p>Note that this must be set before the surface view's containing
441 * window is attached to the window manager.
442 *
443 * <p>See {@link android.view.Display#FLAG_SECURE} for details.
444 *
445 * @param isSecure True if the surface view is secure.
446 */
447 public void setSecure(boolean isSecure) {
448 if (isSecure) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800449 mSurfaceFlags |= SurfaceControl.SECURE;
Jeff Brownf0681b32012-10-23 17:35:57 -0700450 } else {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800451 mSurfaceFlags &= ~SurfaceControl.SECURE;
Jeff Brownf0681b32012-10-23 17:35:57 -0700452 }
453 }
454
Robert Carr55235552017-06-02 14:21:03 -0700455 private void updateOpaqueFlag() {
Robert Carr851e7e42017-06-06 14:04:50 -0700456 if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
Robert Carr55235552017-06-02 14:21:03 -0700457 mSurfaceFlags |= SurfaceControl.OPAQUE;
458 } else {
459 mSurfaceFlags &= ~SurfaceControl.OPAQUE;
460 }
461 }
462
Robert Carrd5c7dd62017-03-08 10:39:30 -0800463 private Rect getParentSurfaceInsets() {
464 final ViewRootImpl root = getViewRootImpl();
465 if (root == null) {
466 return null;
467 } else {
468 return root.mWindowAttributes.surfaceInsets;
469 }
Jeff Tinker3896db12017-03-03 00:20:22 +0000470 }
471
Youngsang Cho9a22f0f2014-04-09 22:51:54 +0900472 /** @hide */
Robert Carrd5c7dd62017-03-08 10:39:30 -0800473 protected void updateSurface() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700474 if (!mHaveFrame) {
475 return;
476 }
Jeff Browna175a5b2012-02-15 19:18:31 -0800477 ViewRootImpl viewRoot = getViewRootImpl();
Robert Carrd5c7dd62017-03-08 10:39:30 -0800478 if (viewRoot == null || viewRoot.mSurface == null || !viewRoot.mSurface.isValid()) {
479 return;
Joe Onorato168173a2009-08-12 21:40:29 -0700480 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700481
Robert Carrd5c7dd62017-03-08 10:39:30 -0800482 mTranslator = viewRoot.mTranslator;
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700483 if (mTranslator != null) {
484 mSurface.setCompatibilityTranslator(mTranslator);
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700485 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700486
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700487 int myWidth = mRequestedWidth;
488 if (myWidth <= 0) myWidth = getWidth();
489 int myHeight = mRequestedHeight;
490 if (myHeight <= 0) myHeight = getHeight();
Mitsuru Oshima001a6e522009-05-11 21:14:03 -0700491
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700492 final boolean formatChanged = mFormat != mRequestedFormat;
Robert Carr7c67b7d2017-07-06 15:28:34 -0700493 final boolean visibleChanged = mVisible != mRequestedVisible;
494 final boolean creating = (mSurfaceControl == null || formatChanged || visibleChanged)
Robert Carrd5c7dd62017-03-08 10:39:30 -0800495 && mRequestedVisible;
496 final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800497 final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
Robert Carr49b593e2016-07-11 12:21:18 -0700498 boolean redrawNeeded = false;
499
Robert Carrd5c7dd62017-03-08 10:39:30 -0800500 if (creating || formatChanged || sizeChanged || visibleChanged || windowVisibleChanged) {
John Reckf6481082016-02-02 15:18:23 -0800501 getLocationInWindow(mLocation);
502
John Reckaa6e84f2016-06-16 15:36:13 -0700503 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
504 + "Changes: creating=" + creating
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700505 + " format=" + formatChanged + " size=" + sizeChanged
506 + " visible=" + visibleChanged
Robert Carr64aadd02015-11-06 13:54:20 -0800507 + " left=" + (mWindowSpaceLeft != mLocation[0])
508 + " top=" + (mWindowSpaceTop != mLocation[1]));
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700509
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700510 try {
511 final boolean visible = mVisible = mRequestedVisible;
Robert Carr64aadd02015-11-06 13:54:20 -0800512 mWindowSpaceLeft = mLocation[0];
513 mWindowSpaceTop = mLocation[1];
Robert Carrd5c7dd62017-03-08 10:39:30 -0800514 mSurfaceWidth = myWidth;
515 mSurfaceHeight = myHeight;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700516 mFormat = mRequestedFormat;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800517 mLastWindowVisibility = mWindowVisibility;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700518
Robert Carrd5c7dd62017-03-08 10:39:30 -0800519 mScreenRect.left = mWindowSpaceLeft;
520 mScreenRect.top = mWindowSpaceTop;
521 mScreenRect.right = mWindowSpaceLeft + getWidth();
522 mScreenRect.bottom = mWindowSpaceTop + getHeight();
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700523 if (mTranslator != null) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800524 mTranslator.translateRectInAppWindowToScreen(mScreenRect);
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700525 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700526
Robert Carrd5c7dd62017-03-08 10:39:30 -0800527 final Rect surfaceInsets = getParentSurfaceInsets();
528 mScreenRect.offset(surfaceInsets.left, surfaceInsets.top);
529
530 if (creating) {
531 mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
Robert Carr3bc95b52017-03-20 21:57:23 -0700532 mDeferredDestroySurfaceControl = mSurfaceControl;
Robert Carr55235552017-06-02 14:21:03 -0700533
534 updateOpaqueFlag();
535 mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
Robert Carrd5c7dd62017-03-08 10:39:30 -0800536 "SurfaceView - " + viewRoot.getTitle().toString(),
537 mSurfaceWidth, mSurfaceHeight, mFormat,
538 mSurfaceFlags);
Robert Carr44ab5752017-03-20 21:47:11 -0700539 } else if (mSurfaceControl == null) {
540 return;
Robert Carr64aadd02015-11-06 13:54:20 -0800541 }
542
Robert Carrd5c7dd62017-03-08 10:39:30 -0800543 boolean realSizeChanged = false;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800544
Dianne Hackborn726426e2010-03-31 22:04:36 -0700545 mSurfaceLock.lock();
546 try {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700547 mDrawingStopped = !visible;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700548
John Reckaa6e84f2016-06-16 15:36:13 -0700549 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
550 + "Cur surface: " + mSurface);
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800551
Robert Carrd5c7dd62017-03-08 10:39:30 -0800552 SurfaceControl.openTransaction();
553 try {
554 mSurfaceControl.setLayer(mSubLayer);
555 if (mViewVisibility) {
556 mSurfaceControl.show();
557 } else {
558 mSurfaceControl.hide();
559 }
560
561 // While creating the surface, we will set it's initial
562 // geometry. Outside of that though, we should generally
563 // leave it to the RenderThread.
Robert Carr511719f2017-03-13 15:27:15 -0700564 //
565 // There is one more case when the buffer size changes we aren't yet
566 // prepared to sync (as even following the transaction applying
567 // we still need to latch a buffer).
568 // b/28866173
569 if (sizeChanged || creating || !mRtHandlingPositionUpdates) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800570 mSurfaceControl.setPosition(mScreenRect.left, mScreenRect.top);
571 mSurfaceControl.setMatrix(mScreenRect.width() / (float) mSurfaceWidth,
572 0.0f, 0.0f,
573 mScreenRect.height() / (float) mSurfaceHeight);
574 }
575 if (sizeChanged) {
576 mSurfaceControl.setSize(mSurfaceWidth, mSurfaceHeight);
577 }
578 } finally {
579 SurfaceControl.closeTransaction();
Dianne Hackborn726426e2010-03-31 22:04:36 -0700580 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800581
Robert Carrd5c7dd62017-03-08 10:39:30 -0800582 if (sizeChanged || creating) {
583 redrawNeeded = true;
584 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800585
Dianne Hackborn726426e2010-03-31 22:04:36 -0700586 mSurfaceFrame.left = 0;
587 mSurfaceFrame.top = 0;
588 if (mTranslator == null) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800589 mSurfaceFrame.right = mSurfaceWidth;
590 mSurfaceFrame.bottom = mSurfaceHeight;
Dianne Hackborn726426e2010-03-31 22:04:36 -0700591 } else {
592 float appInvertedScale = mTranslator.applicationInvertedScale;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800593 mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f);
594 mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f);
Dianne Hackborn726426e2010-03-31 22:04:36 -0700595 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700596
Dianne Hackborn726426e2010-03-31 22:04:36 -0700597 final int surfaceWidth = mSurfaceFrame.right;
598 final int surfaceHeight = mSurfaceFrame.bottom;
599 realSizeChanged = mLastSurfaceWidth != surfaceWidth
600 || mLastSurfaceHeight != surfaceHeight;
601 mLastSurfaceWidth = surfaceWidth;
602 mLastSurfaceHeight = surfaceHeight;
603 } finally {
604 mSurfaceLock.unlock();
Mitsuru Oshima589cebe2009-07-22 20:38:58 -0700605 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700606
607 try {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800608 redrawNeeded |= visible && !mDrawFinished;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700609
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800610 SurfaceHolder.Callback callbacks[] = null;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700611
Robert Carrd5c7dd62017-03-08 10:39:30 -0800612 final boolean surfaceChanged = creating;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800613 if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
614 mSurfaceCreated = false;
615 if (mSurface.isValid()) {
John Reckaa6e84f2016-06-16 15:36:13 -0700616 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
617 + "visibleChanged -- surfaceDestroyed");
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800618 callbacks = getSurfaceCallbacks();
619 for (SurfaceHolder.Callback c : callbacks) {
620 c.surfaceDestroyed(mSurfaceHolder);
621 }
Robert Carr387838b2016-09-07 14:12:44 -0700622 // Since Android N the same surface may be reused and given to us
623 // again by the system server at a later point. However
624 // as we didn't do this in previous releases, clients weren't
625 // necessarily required to clean up properly in
626 // surfaceDestroyed. This leads to problems for example when
627 // clients don't destroy their EGL context, and try
628 // and create a new one on the same surface following reuse.
629 // Since there is no valid use of the surface in-between
630 // surfaceDestroyed and surfaceCreated, we force a disconnect,
631 // so the next connect will always work if we end up reusing
632 // the surface.
John Reck6ba466f2016-09-30 14:30:04 -0700633 if (mSurface.isValid()) {
634 mSurface.forceScopedDisconnect();
635 }
Mitsuru Oshima3d914922009-05-13 22:29:15 -0700636 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800637 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700638
Robert Carrd5c7dd62017-03-08 10:39:30 -0800639 if (creating) {
640 mSurface.copyFrom(mSurfaceControl);
641 }
642
Bryce Lee453fc362017-06-20 10:47:55 -0700643 if (sizeChanged && getContext().getApplicationInfo().targetSdkVersion
Bryce Lee02949f12017-06-16 07:20:34 -0700644 < Build.VERSION_CODES.O) {
645 // Some legacy applications use the underlying native {@link Surface} object
646 // as a key to whether anything has changed. In these cases, updates to the
647 // existing {@link Surface} will be ignored when the size changes.
648 // Therefore, we must explicitly recreate the {@link Surface} in these
649 // cases.
650 mSurface.createFrom(mSurfaceControl);
651 }
652
Andreas Röhlf750b8c2012-07-02 13:06:26 +0200653 if (visible && mSurface.isValid()) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800654 if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
655 mSurfaceCreated = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700656 mIsCreating = true;
John Reckaa6e84f2016-06-16 15:36:13 -0700657 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
658 + "visibleChanged -- surfaceCreated");
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800659 if (callbacks == null) {
660 callbacks = getSurfaceCallbacks();
661 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700662 for (SurfaceHolder.Callback c : callbacks) {
663 c.surfaceCreated(mSurfaceHolder);
664 }
665 }
666 if (creating || formatChanged || sizeChanged
Dianne Hackborn726426e2010-03-31 22:04:36 -0700667 || visibleChanged || realSizeChanged) {
John Reckaa6e84f2016-06-16 15:36:13 -0700668 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
669 + "surfaceChanged -- format=" + mFormat
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800670 + " w=" + myWidth + " h=" + myHeight);
671 if (callbacks == null) {
672 callbacks = getSurfaceCallbacks();
673 }
Dianne Hackborn251fd432010-07-14 16:56:31 -0700674 for (SurfaceHolder.Callback c : callbacks) {
675 c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
676 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700677 }
678 if (redrawNeeded) {
John Reckaa6e84f2016-06-16 15:36:13 -0700679 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
680 + "surfaceRedrawNeeded");
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800681 if (callbacks == null) {
682 callbacks = getSurfaceCallbacks();
683 }
Robert Carr8508bb22017-03-27 15:46:27 -0700684
685 mPendingReportDraws++;
686 viewRoot.drawPending();
Robert Carr25cfa132016-11-16 13:24:09 -0800687 SurfaceCallbackHelper sch =
Robert Carrd5c7dd62017-03-08 10:39:30 -0800688 new SurfaceCallbackHelper(this::onDrawFinished);
Robert Carr25cfa132016-11-16 13:24:09 -0800689 sch.dispatchSurfaceRedrawNeededAsync(mSurfaceHolder, callbacks);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700690 }
691 }
692 } finally {
693 mIsCreating = false;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800694 if (mSurfaceControl != null && !mSurfaceCreated) {
Robert Carrde844432017-05-04 13:45:45 -0700695 mSurface.release();
Robert Carr73678092017-05-19 15:06:50 -0700696 // If we are not in the stopped state, then the destruction of the Surface
697 // represents a visual change we need to display, and we should go ahead
698 // and destroy the SurfaceControl. However if we are in the stopped state,
699 // we can just leave the Surface around so it can be a part of animations,
700 // and we let the life-time be tied to the parent surface.
701 if (!mWindowStopped) {
702 mSurfaceControl.destroy();
703 mSurfaceControl = null;
704 }
Robert Carrd5c7dd62017-03-08 10:39:30 -0800705 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700706 }
Robert Carrd5c7dd62017-03-08 10:39:30 -0800707 } catch (Exception ex) {
Robert Carr44ab5752017-03-20 21:47:11 -0700708 Log.e(TAG, "Exception configuring surface", ex);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700709 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800710 if (DEBUG) Log.v(
Robert Carrd5c7dd62017-03-08 10:39:30 -0800711 TAG, "Layout: x=" + mScreenRect.left + " y=" + mScreenRect.top
712 + " w=" + mScreenRect.width() + " h=" + mScreenRect.height()
713 + ", frame=" + mSurfaceFrame);
John Reckf23a1b82016-06-22 14:23:31 -0700714 } else {
715 // Calculate the window position in case RT loses the window
716 // and we need to fallback to a UI-thread driven position update
Robert Carrd5c7dd62017-03-08 10:39:30 -0800717 getLocationInSurface(mLocation);
John Reckf6481082016-02-02 15:18:23 -0800718 final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
719 || mWindowSpaceTop != mLocation[1];
Robert Carrd5c7dd62017-03-08 10:39:30 -0800720 final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
721 || getHeight() != mScreenRect.height();
John Reckf6481082016-02-02 15:18:23 -0800722 if (positionChanged || layoutSizeChanged) { // Only the position has changed
723 mWindowSpaceLeft = mLocation[0];
724 mWindowSpaceTop = mLocation[1];
Robert Carrd5c7dd62017-03-08 10:39:30 -0800725 // For our size changed check, we keep mScreenRect.width() and mScreenRect.height()
John Reckf6481082016-02-02 15:18:23 -0800726 // in view local space.
Robert Carrd5c7dd62017-03-08 10:39:30 -0800727 mLocation[0] = getWidth();
728 mLocation[1] = getHeight();
Robert Carr64aadd02015-11-06 13:54:20 -0800729
Robert Carrd5c7dd62017-03-08 10:39:30 -0800730 mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
Robert Carrc90e5f82017-07-18 13:10:02 -0700731 mWindowSpaceLeft + mLocation[0], mWindowSpaceTop + mLocation[1]);
John Reckf057fb52016-04-15 13:46:29 -0700732
733 if (mTranslator != null) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800734 mTranslator.translateRectInAppWindowToScreen(mScreenRect);
John Reckf057fb52016-04-15 13:46:29 -0700735 }
736
Robert Carr3651ab82017-04-25 12:05:34 -0700737 if (mSurfaceControl == null) {
738 return;
739 }
740
Bryce Lee16e50892017-04-11 01:59:37 +0000741 if (!isHardwareAccelerated() || !mRtHandlingPositionUpdates) {
John Reckf23a1b82016-06-22 14:23:31 -0700742 try {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800743 if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition UI, " +
John Reckf23a1b82016-06-22 14:23:31 -0700744 "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
Robert Carrd5c7dd62017-03-08 10:39:30 -0800745 mScreenRect.left, mScreenRect.top,
746 mScreenRect.right, mScreenRect.bottom));
747 setParentSpaceRectangle(mScreenRect, -1);
748 } catch (Exception ex) {
Robert Carr44ab5752017-03-20 21:47:11 -0700749 Log.e(TAG, "Exception configuring surface", ex);
John Reckf23a1b82016-06-22 14:23:31 -0700750 }
John Reckf6481082016-02-02 15:18:23 -0800751 }
Rob Carr64e516f2015-10-29 00:20:45 +0000752 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700753 }
754 }
755
Robert Carrd5c7dd62017-03-08 10:39:30 -0800756 private void onDrawFinished() {
757 if (DEBUG) {
758 Log.i(TAG, System.identityHashCode(this) + " "
759 + "finishedDrawing");
760 }
Robert Carr3bc95b52017-03-20 21:57:23 -0700761
762 if (mDeferredDestroySurfaceControl != null) {
763 mDeferredDestroySurfaceControl.destroy();
764 mDeferredDestroySurfaceControl = null;
765 }
766
John Reck79925002017-05-26 13:57:14 -0700767 runOnUiThread(() -> {
Robert Carrb53670a2017-05-25 18:20:49 -0700768 performDrawFinished();
John Reck79925002017-05-26 13:57:14 -0700769 });
Robert Carrd5c7dd62017-03-08 10:39:30 -0800770 }
771
772 private void setParentSpaceRectangle(Rect position, long frameNumber) {
773 ViewRootImpl viewRoot = getViewRootImpl();
774
775 SurfaceControl.openTransaction();
776 try {
777 if (frameNumber > 0) {
778 mSurfaceControl.deferTransactionUntil(viewRoot.mSurface, frameNumber);
779 }
780 mSurfaceControl.setPosition(position.left, position.top);
781 mSurfaceControl.setMatrix(position.width() / (float) mSurfaceWidth,
782 0.0f, 0.0f,
783 position.height() / (float) mSurfaceHeight);
784 } finally {
785 SurfaceControl.closeTransaction();
786 }
787 }
788
John Reckf6481082016-02-02 15:18:23 -0800789 private Rect mRTLastReportedPosition = new Rect();
790
791 /**
Robert Carr33879132016-09-06 14:41:40 -0700792 * Called by native by a Rendering Worker thread to update the window position
John Reckf6481082016-02-02 15:18:23 -0800793 * @hide
794 */
Robert Carrd5c7dd62017-03-08 10:39:30 -0800795 public final void updateSurfacePosition_renderWorker(long frameNumber,
John Reckf6481082016-02-02 15:18:23 -0800796 int left, int top, int right, int bottom) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800797 if (mSurfaceControl == null) {
John Reckf6481082016-02-02 15:18:23 -0800798 return;
799 }
Robert Carrd5c7dd62017-03-08 10:39:30 -0800800
John Reckf23a1b82016-06-22 14:23:31 -0700801 // TODO: This is teensy bit racey in that a brand new SurfaceView moving on
802 // its 2nd frame if RenderThread is running slowly could potentially see
803 // this as false, enter the branch, get pre-empted, then this comes along
804 // and reports a new position, then the UI thread resumes and reports
805 // its position. This could therefore be de-sync'd in that interval, but
806 // the synchronization would violate the rule that RT must never block
807 // on the UI thread which would open up potential deadlocks. The risk of
808 // a single-frame desync is therefore preferable for now.
809 mRtHandlingPositionUpdates = true;
John Reckf6481082016-02-02 15:18:23 -0800810 if (mRTLastReportedPosition.left == left
811 && mRTLastReportedPosition.top == top
812 && mRTLastReportedPosition.right == right
813 && mRTLastReportedPosition.bottom == bottom) {
814 return;
815 }
816 try {
817 if (DEBUG) {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800818 Log.d(TAG, String.format("%d updateSurfacePosition RenderWorker, frameNr = %d, " +
John Reckaa6e84f2016-06-16 15:36:13 -0700819 "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
820 frameNumber, left, top, right, bottom));
John Reckf6481082016-02-02 15:18:23 -0800821 }
Wonsik Kim5aec7b92017-03-07 17:15:50 -0800822 mRTLastReportedPosition.set(left, top, right, bottom);
Robert Carrd5c7dd62017-03-08 10:39:30 -0800823 setParentSpaceRectangle(mRTLastReportedPosition, frameNumber);
824 // Now overwrite mRTLastReportedPosition with our values
825 } catch (Exception ex) {
John Reckf6481082016-02-02 15:18:23 -0800826 Log.e(TAG, "Exception from repositionChild", ex);
827 }
828 }
829
John Reckaa6e84f2016-06-16 15:36:13 -0700830 /**
Robert Carrd5c7dd62017-03-08 10:39:30 -0800831 * Called by native on RenderThread to notify that the view is no longer in the
Robert Carr33879132016-09-06 14:41:40 -0700832 * draw tree. UI thread is blocked at this point.
John Reckaa6e84f2016-06-16 15:36:13 -0700833 * @hide
834 */
Robert Carrd5c7dd62017-03-08 10:39:30 -0800835 public final void surfacePositionLost_uiRtSync(long frameNumber) {
John Reckaa6e84f2016-06-16 15:36:13 -0700836 if (DEBUG) {
Robert Carr33879132016-09-06 14:41:40 -0700837 Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
John Reckaa6e84f2016-06-16 15:36:13 -0700838 System.identityHashCode(this), frameNumber));
839 }
Robert Carrad3a4932017-06-20 14:55:21 -0700840 mRTLastReportedPosition.setEmpty();
841
Robert Carrd5c7dd62017-03-08 10:39:30 -0800842 if (mSurfaceControl == null) {
John Reck474659c2016-06-27 07:56:37 -0700843 return;
844 }
John Reckf23a1b82016-06-22 14:23:31 -0700845 if (mRtHandlingPositionUpdates) {
846 mRtHandlingPositionUpdates = false;
847 // This callback will happen while the UI thread is blocked, so we can
848 // safely access other member variables at this time.
849 // So do what the UI thread would have done if RT wasn't handling position
850 // updates.
Robert Carrd5c7dd62017-03-08 10:39:30 -0800851 if (!mScreenRect.isEmpty() && !mScreenRect.equals(mRTLastReportedPosition)) {
John Reckf23a1b82016-06-22 14:23:31 -0700852 try {
Robert Carrd5c7dd62017-03-08 10:39:30 -0800853 if (DEBUG) Log.d(TAG, String.format("%d updateSurfacePosition, " +
John Reckf23a1b82016-06-22 14:23:31 -0700854 "postion = [%d, %d, %d, %d]", System.identityHashCode(this),
Robert Carrd5c7dd62017-03-08 10:39:30 -0800855 mScreenRect.left, mScreenRect.top,
856 mScreenRect.right, mScreenRect.bottom));
857 setParentSpaceRectangle(mScreenRect, frameNumber);
858 } catch (Exception ex) {
Robert Carr44ab5752017-03-20 21:47:11 -0700859 Log.e(TAG, "Exception configuring surface", ex);
John Reckf23a1b82016-06-22 14:23:31 -0700860 }
861 }
John Reckf23a1b82016-06-22 14:23:31 -0700862 }
John Reckaa6e84f2016-06-16 15:36:13 -0700863 }
864
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800865 private SurfaceHolder.Callback[] getSurfaceCallbacks() {
866 SurfaceHolder.Callback callbacks[];
867 synchronized (mCallbacks) {
868 callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
869 mCallbacks.toArray(callbacks);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700870 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800871 return callbacks;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700872 }
873
Yohei Yukawa9309c192017-09-09 17:45:27 -0700874 /**
875 * This method still exists only for compatibility reasons because some applications have relied
876 * on this method via reflection. See Issue 36345857 for details.
877 *
878 * @deprecated No platform code is using this method anymore.
879 * @hide
880 */
881 @Deprecated
882 public void setWindowType(int type) {
883 if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
884 throw new UnsupportedOperationException(
885 "SurfaceView#setWindowType() has never been a public API.");
886 }
887
888 if (type == TYPE_APPLICATION_PANEL) {
889 Log.e(TAG, "If you are calling SurfaceView#setWindowType(TYPE_APPLICATION_PANEL) "
890 + "just to make the SurfaceView to be placed on top of its window, you must "
891 + "call setZOrderOnTop(true) instead.", new Throwable());
892 setZOrderOnTop(true);
893 return;
894 }
895 Log.e(TAG, "SurfaceView#setWindowType(int) is deprecated and now does nothing. "
896 + "type=" + type, new Throwable());
897 }
898
John Reck79925002017-05-26 13:57:14 -0700899 private void runOnUiThread(Runnable runnable) {
900 Handler handler = getHandler();
901 if (handler != null && handler.getLooper() != Looper.myLooper()) {
902 handler.post(runnable);
903 } else {
904 runnable.run();
905 }
906 }
907
Yohei Yukawa3b5011a2017-03-16 15:34:12 -0700908 /**
Derek Sollenberger7179b812010-03-22 13:41:20 -0400909 * Check to see if the surface has fixed size dimensions or if the surface's
910 * dimensions are dimensions are dependent on its current layout.
911 *
912 * @return true if the surface has dimensions that are fixed in size
913 * @hide
914 */
915 public boolean isFixedSize() {
916 return (mRequestedWidth != -1 || mRequestedHeight != -1);
917 }
918
Robert Carrd5c7dd62017-03-08 10:39:30 -0800919 private boolean isAboveParent() {
920 return mSubLayer >= 0;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700921 }
922
Igor Murashkina86ab6402013-08-30 12:58:36 -0700923 private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700924 private static final String LOG_TAG = "SurfaceHolder";
Igor Murashkina86ab6402013-08-30 12:58:36 -0700925
926 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700927 public boolean isCreating() {
928 return mIsCreating;
929 }
930
Igor Murashkina86ab6402013-08-30 12:58:36 -0700931 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700932 public void addCallback(Callback callback) {
933 synchronized (mCallbacks) {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700934 // This is a linear search, but in practice we'll
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700935 // have only a couple callbacks, so it doesn't matter.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700936 if (mCallbacks.contains(callback) == false) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700937 mCallbacks.add(callback);
938 }
939 }
940 }
941
Igor Murashkina86ab6402013-08-30 12:58:36 -0700942 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700943 public void removeCallback(Callback callback) {
944 synchronized (mCallbacks) {
945 mCallbacks.remove(callback);
946 }
947 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700948
949 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700950 public void setFixedSize(int width, int height) {
951 if (mRequestedWidth != width || mRequestedHeight != height) {
952 mRequestedWidth = width;
953 mRequestedHeight = height;
954 requestLayout();
955 }
956 }
957
Igor Murashkina86ab6402013-08-30 12:58:36 -0700958 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700959 public void setSizeFromLayout() {
960 if (mRequestedWidth != -1 || mRequestedHeight != -1) {
961 mRequestedWidth = mRequestedHeight = -1;
962 requestLayout();
963 }
964 }
965
Igor Murashkina86ab6402013-08-30 12:58:36 -0700966 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700967 public void setFormat(int format) {
Mathias Agopian2d468c52010-06-14 21:50:48 -0700968 // for backward compatibility reason, OPAQUE always
969 // means 565 for SurfaceView
970 if (format == PixelFormat.OPAQUE)
971 format = PixelFormat.RGB_565;
972
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700973 mRequestedFormat = format;
Robert Carrd5c7dd62017-03-08 10:39:30 -0800974 if (mSurfaceControl != null) {
975 updateSurface();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700976 }
977 }
978
Mathias Agopiand2112302010-12-07 19:38:17 -0800979 /**
980 * @deprecated setType is now ignored.
981 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700982 @Override
Mathias Agopiand2112302010-12-07 19:38:17 -0800983 @Deprecated
984 public void setType(int type) { }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700985
Igor Murashkina86ab6402013-08-30 12:58:36 -0700986 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700987 public void setKeepScreenOn(boolean screenOn) {
John Reck79925002017-05-26 13:57:14 -0700988 runOnUiThread(() -> SurfaceView.this.setKeepScreenOn(screenOn));
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700989 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700990
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700991 /**
992 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
993 *
994 * After drawing into the provided {@link Canvas}, the caller must
995 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
996 *
997 * The caller must redraw the entire surface.
998 * @return A canvas for drawing into the surface.
999 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07001000 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001001 public Canvas lockCanvas() {
John Reck6bc70142016-10-26 16:49:17 -07001002 return internalLockCanvas(null, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001003 }
1004
Mathias Agopian9ddf32a2013-04-17 15:04:47 -07001005 /**
1006 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
1007 *
1008 * After drawing into the provided {@link Canvas}, the caller must
1009 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
1010 *
1011 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
1012 * to redraw. This function may choose to expand the dirty rectangle if for example
1013 * the surface has been resized or if the previous contents of the surface were
1014 * not available. The caller must redraw the entire dirty region as represented
1015 * by the contents of the inOutDirty rectangle upon return from this function.
1016 * The caller may also pass <code>null</code> instead, in the case where the
1017 * entire surface should be redrawn.
1018 * @return A canvas for drawing into the surface.
1019 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07001020 @Override
Mathias Agopian9ddf32a2013-04-17 15:04:47 -07001021 public Canvas lockCanvas(Rect inOutDirty) {
John Reck6bc70142016-10-26 16:49:17 -07001022 return internalLockCanvas(inOutDirty, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001023 }
1024
John Reck6bc70142016-10-26 16:49:17 -07001025 @Override
1026 public Canvas lockHardwareCanvas() {
1027 return internalLockCanvas(null, true);
1028 }
1029
1030 private Canvas internalLockCanvas(Rect dirty, boolean hardware) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001031 mSurfaceLock.lock();
1032
John Reckaa6e84f2016-06-16 15:36:13 -07001033 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Locking canvas... stopped="
Robert Carrd5c7dd62017-03-08 10:39:30 -08001034 + mDrawingStopped + ", surfaceControl=" + mSurfaceControl);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001035
1036 Canvas c = null;
Robert Carrd5c7dd62017-03-08 10:39:30 -08001037 if (!mDrawingStopped && mSurfaceControl != null) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001038 try {
John Reck6bc70142016-10-26 16:49:17 -07001039 if (hardware) {
1040 c = mSurface.lockHardwareCanvas();
1041 } else {
1042 c = mSurface.lockCanvas(dirty);
1043 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001044 } catch (Exception e) {
1045 Log.e(LOG_TAG, "Exception locking surface", e);
1046 }
1047 }
1048
John Reckaa6e84f2016-06-16 15:36:13 -07001049 if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + "Returned canvas: " + c);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001050 if (c != null) {
1051 mLastLockTime = SystemClock.uptimeMillis();
1052 return c;
1053 }
Igor Murashkina86ab6402013-08-30 12:58:36 -07001054
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001055 // If the Surface is not ready to be drawn, then return null,
1056 // but throttle calls to this function so it isn't called more
1057 // than every 100ms.
1058 long now = SystemClock.uptimeMillis();
1059 long nextTime = mLastLockTime + 100;
1060 if (nextTime > now) {
1061 try {
1062 Thread.sleep(nextTime-now);
1063 } catch (InterruptedException e) {
1064 }
1065 now = SystemClock.uptimeMillis();
1066 }
1067 mLastLockTime = now;
1068 mSurfaceLock.unlock();
Igor Murashkina86ab6402013-08-30 12:58:36 -07001069
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001070 return null;
1071 }
1072
Mathias Agopian9ddf32a2013-04-17 15:04:47 -07001073 /**
1074 * Posts the new contents of the {@link Canvas} to the surface and
1075 * releases the {@link Canvas}.
1076 *
1077 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
1078 */
Igor Murashkina86ab6402013-08-30 12:58:36 -07001079 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001080 public void unlockCanvasAndPost(Canvas canvas) {
1081 mSurface.unlockCanvasAndPost(canvas);
1082 mSurfaceLock.unlock();
1083 }
1084
Igor Murashkina86ab6402013-08-30 12:58:36 -07001085 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001086 public Surface getSurface() {
1087 return mSurface;
1088 }
1089
Igor Murashkina86ab6402013-08-30 12:58:36 -07001090 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001091 public Rect getSurfaceFrame() {
1092 return mSurfaceFrame;
1093 }
1094 };
Robert Carr55235552017-06-02 14:21:03 -07001095
1096 class SurfaceControlWithBackground extends SurfaceControl {
1097 private SurfaceControl mBackgroundControl;
1098 private boolean mOpaque = true;
1099 public boolean mVisible = false;
1100
1101 public SurfaceControlWithBackground(SurfaceSession s,
1102 String name, int w, int h, int format, int flags)
1103 throws Exception {
1104 super(s, name, w, h, format, flags);
1105 mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
1106 PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
1107 mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
1108 }
1109
1110 @Override
1111 public void setAlpha(float alpha) {
1112 super.setAlpha(alpha);
1113 mBackgroundControl.setAlpha(alpha);
1114 }
1115
1116 @Override
1117 public void setLayer(int zorder) {
1118 super.setLayer(zorder);
1119 // -3 is below all other child layers as SurfaceView never goes below -2
1120 mBackgroundControl.setLayer(-3);
1121 }
1122
1123 @Override
1124 public void setPosition(float x, float y) {
1125 super.setPosition(x, y);
1126 mBackgroundControl.setPosition(x, y);
1127 }
1128
1129 @Override
1130 public void setSize(int w, int h) {
1131 super.setSize(w, h);
1132 mBackgroundControl.setSize(w, h);
1133 }
1134
1135 @Override
1136 public void setWindowCrop(Rect crop) {
1137 super.setWindowCrop(crop);
1138 mBackgroundControl.setWindowCrop(crop);
1139 }
1140
1141 @Override
1142 public void setFinalCrop(Rect crop) {
1143 super.setFinalCrop(crop);
1144 mBackgroundControl.setFinalCrop(crop);
1145 }
1146
1147 @Override
1148 public void setLayerStack(int layerStack) {
1149 super.setLayerStack(layerStack);
1150 mBackgroundControl.setLayerStack(layerStack);
1151 }
1152
1153 @Override
1154 public void setOpaque(boolean isOpaque) {
1155 super.setOpaque(isOpaque);
1156 mOpaque = isOpaque;
1157 updateBackgroundVisibility();
1158 }
1159
1160 @Override
1161 public void setSecure(boolean isSecure) {
1162 super.setSecure(isSecure);
1163 }
1164
1165 @Override
1166 public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
1167 super.setMatrix(dsdx, dtdx, dsdy, dtdy);
1168 mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
1169 }
1170
1171 @Override
1172 public void hide() {
1173 super.hide();
1174 mVisible = false;
1175 updateBackgroundVisibility();
1176 }
1177
1178 @Override
1179 public void show() {
1180 super.show();
1181 mVisible = true;
1182 updateBackgroundVisibility();
1183 }
1184
1185 @Override
1186 public void destroy() {
1187 super.destroy();
1188 mBackgroundControl.destroy();
1189 }
1190
1191 @Override
1192 public void release() {
1193 super.release();
1194 mBackgroundControl.release();
1195 }
1196
1197 @Override
1198 public void setTransparentRegionHint(Region region) {
1199 super.setTransparentRegionHint(region);
1200 mBackgroundControl.setTransparentRegionHint(region);
1201 }
1202
1203 @Override
1204 public void deferTransactionUntil(IBinder handle, long frame) {
1205 super.deferTransactionUntil(handle, frame);
1206 mBackgroundControl.deferTransactionUntil(handle, frame);
1207 }
1208
Robert Carr552da0e2017-06-12 11:43:51 -07001209 @Override
1210 public void deferTransactionUntil(Surface barrier, long frame) {
1211 super.deferTransactionUntil(barrier, frame);
1212 mBackgroundControl.deferTransactionUntil(barrier, frame);
1213 }
1214
Robert Carr55235552017-06-02 14:21:03 -07001215 void updateBackgroundVisibility() {
1216 if (mOpaque && mVisible) {
1217 mBackgroundControl.show();
1218 } else {
1219 mBackgroundControl.hide();
1220 }
1221 }
1222 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001223}