blob: 65d3f6d06413448e64f322881010ba26e0e12022 [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
Dianne Hackborn72c82ab2009-08-11 21:13:54 -070019import com.android.internal.view.BaseIWindow;
20
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070021import android.content.Context;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080022import android.content.res.Configuration;
Mitsuru Oshima64f59342009-06-21 00:03:11 -070023import android.content.res.CompatibilityInfo.Translator;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070024import android.graphics.Canvas;
25import android.graphics.PixelFormat;
26import android.graphics.PorterDuff;
27import android.graphics.Rect;
28import android.graphics.Region;
29import android.os.Handler;
30import android.os.Message;
31import android.os.RemoteException;
32import android.os.SystemClock;
33import android.os.ParcelFileDescriptor;
34import android.util.AttributeSet;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070035import android.util.Log;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070036
Jon Larimer9bdf5762009-01-02 18:55:15 -050037import java.lang.ref.WeakReference;
38import java.util.ArrayList;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070039import java.util.concurrent.locks.ReentrantLock;
40
41/**
42 * Provides a dedicated drawing surface embedded inside of a view hierarchy.
43 * You can control the format of this surface and, if you like, its size; the
44 * SurfaceView takes care of placing the surface at the correct location on the
45 * screen
Igor Murashkina86ab6402013-08-30 12:58:36 -070046 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070047 * <p>The surface is Z ordered so that it is behind the window holding its
48 * SurfaceView; the SurfaceView punches a hole in its window to allow its
Jesse Hallc9f345f2012-09-26 11:55:16 -070049 * surface to be displayed. The view hierarchy will take care of correctly
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070050 * compositing with the Surface any siblings of the SurfaceView that would
Jesse Hallc9f345f2012-09-26 11:55:16 -070051 * 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 -070052 * buttons on top of the Surface, though note however that it can have an
53 * impact on performance since a full alpha-blended composite will be performed
54 * each time the Surface changes.
Igor Murashkina86ab6402013-08-30 12:58:36 -070055 *
Jesse Hallc9f345f2012-09-26 11:55:16 -070056 * <p> The transparent region that makes the surface visible is based on the
57 * layout positions in the view hierarchy. If the post-layout transform
58 * properties are used to draw a sibling view on top of the SurfaceView, the
59 * view may not be properly composited with the surface.
60 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070061 * <p>Access to the underlying surface is provided via the SurfaceHolder interface,
62 * which can be retrieved by calling {@link #getHolder}.
Igor Murashkina86ab6402013-08-30 12:58:36 -070063 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070064 * <p>The Surface will be created for you while the SurfaceView's window is
65 * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated}
66 * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the
67 * Surface is created and destroyed as the window is shown and hidden.
Igor Murashkina86ab6402013-08-30 12:58:36 -070068 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070069 * <p>One of the purposes of this class is to provide a surface in which a
Jesse Hallc9f345f2012-09-26 11:55:16 -070070 * secondary thread can render into the screen. If you are going to use it
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070071 * this way, you need to be aware of some threading semantics:
Igor Murashkina86ab6402013-08-30 12:58:36 -070072 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070073 * <ul>
74 * <li> All SurfaceView and
75 * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called
76 * from the thread running the SurfaceView's window (typically the main thread
Jesse Hallc9f345f2012-09-26 11:55:16 -070077 * of the application). They thus need to correctly synchronize with any
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070078 * state that is also touched by the drawing thread.
79 * <li> You must ensure that the drawing thread only touches the underlying
80 * Surface while it is valid -- between
81 * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()}
82 * and
83 * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}.
84 * </ul>
85 */
86public class SurfaceView extends View {
87 static private final String TAG = "SurfaceView";
88 static private final boolean DEBUG = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070089
90 final ArrayList<SurfaceHolder.Callback> mCallbacks
91 = new ArrayList<SurfaceHolder.Callback>();
92
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080093 final int[] mLocation = new int[2];
Igor Murashkina86ab6402013-08-30 12:58:36 -070094
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070095 final ReentrantLock mSurfaceLock = new ReentrantLock();
Dianne Hackborn61566cc2011-12-02 23:31:52 -080096 final Surface mSurface = new Surface(); // Current surface in use
97 final Surface mNewSurface = new Surface(); // New surface we are switching to
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070098 boolean mDrawingStopped = true;
99
100 final WindowManager.LayoutParams mLayout
101 = new WindowManager.LayoutParams();
102 IWindowSession mSession;
103 MyWindow mWindow;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800104 final Rect mVisibleInsets = new Rect();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700105 final Rect mWinFrame = new Rect();
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800106 final Rect mOverscanInsets = new Rect();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800107 final Rect mContentInsets = new Rect();
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700108 final Configuration mConfiguration = new Configuration();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700109
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700110 static final int KEEP_SCREEN_ON_MSG = 1;
111 static final int GET_NEW_SURFACE_MSG = 2;
Dianne Hackborn726426e2010-03-31 22:04:36 -0700112 static final int UPDATE_WINDOW_MSG = 3;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700113
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700114 int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700115
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700116 boolean mIsCreating = false;
117
118 final Handler mHandler = new Handler() {
119 @Override
120 public void handleMessage(Message msg) {
121 switch (msg.what) {
122 case KEEP_SCREEN_ON_MSG: {
123 setKeepScreenOn(msg.arg1 != 0);
124 } break;
125 case GET_NEW_SURFACE_MSG: {
126 handleGetNewSurface();
127 } break;
Dianne Hackborn726426e2010-03-31 22:04:36 -0700128 case UPDATE_WINDOW_MSG: {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700129 updateWindow(false, false);
Dianne Hackborn726426e2010-03-31 22:04:36 -0700130 } break;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700131 }
132 }
133 };
Igor Murashkina86ab6402013-08-30 12:58:36 -0700134
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700135 final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
136 = new ViewTreeObserver.OnScrollChangedListener() {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700137 @Override
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700138 public void onScrollChanged() {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700139 updateWindow(false, false);
Dianne Hackborne2af5c82010-03-18 15:44:34 -0700140 }
141 };
Igor Murashkina86ab6402013-08-30 12:58:36 -0700142
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700143 boolean mRequestedVisible = false;
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700144 boolean mWindowVisibility = false;
145 boolean mViewVisibility = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700146 int mRequestedWidth = -1;
147 int mRequestedHeight = -1;
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700148 /* Set SurfaceView's format to 565 by default to maintain backward
149 * compatibility with applications assuming this format.
150 */
151 int mRequestedFormat = PixelFormat.RGB_565;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700152
153 boolean mHaveFrame = false;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800154 boolean mSurfaceCreated = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700155 long mLastLockTime = 0;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700156
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700157 boolean mVisible = false;
158 int mLeft = -1;
159 int mTop = -1;
160 int mWidth = -1;
161 int mHeight = -1;
162 int mFormat = -1;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700163 final Rect mSurfaceFrame = new Rect();
Dianne Hackborn726426e2010-03-31 22:04:36 -0700164 int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
165 boolean mUpdateWindowNeeded;
166 boolean mReportDrawNeeded;
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700167 private Translator mTranslator;
Romain Guyf2499fa2011-01-26 18:31:23 -0800168
169 private final ViewTreeObserver.OnPreDrawListener mDrawListener =
170 new ViewTreeObserver.OnPreDrawListener() {
171 @Override
172 public boolean onPreDraw() {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700173 // reposition ourselves where the surface is
Romain Guy0c756222011-01-26 18:45:28 -0800174 mHaveFrame = getWidth() > 0 && getHeight() > 0;
Romain Guyf2499fa2011-01-26 18:31:23 -0800175 updateWindow(false, false);
176 return true;
177 }
178 };
Romain Guy01d5edc2011-01-28 11:28:53 -0800179 private boolean mGlobalListenersAdded;
Romain Guyf2499fa2011-01-26 18:31:23 -0800180
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700181 public SurfaceView(Context context) {
182 super(context);
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700183 init();
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) {
187 super(context, attrs);
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700188 init();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700189 }
190
Alan Viverette617feb92013-09-09 18:09:13 -0700191 public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
192 super(context, attrs, defStyleAttr);
193 init();
194 }
195
196 public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
197 super(context, attrs, defStyleAttr, defStyleRes);
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700198 init();
199 }
200
201 private void init() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700202 setWillNotDraw(true);
203 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700204
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700205 /**
206 * Return the SurfaceHolder providing access and control over this
207 * SurfaceView's underlying surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700208 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700209 * @return SurfaceHolder The holder of the surface.
210 */
211 public SurfaceHolder getHolder() {
212 return mSurfaceHolder;
213 }
214
215 @Override
216 protected void onAttachedToWindow() {
217 super.onAttachedToWindow();
218 mParent.requestTransparentRegion(this);
219 mSession = getWindowSession();
220 mLayout.token = getWindowToken();
221 mLayout.setTitle("SurfaceView");
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700222 mViewVisibility = getVisibility() == VISIBLE;
Romain Guy01d5edc2011-01-28 11:28:53 -0800223
224 if (!mGlobalListenersAdded) {
225 ViewTreeObserver observer = getViewTreeObserver();
226 observer.addOnScrollChangedListener(mScrollChangedListener);
227 observer.addOnPreDrawListener(mDrawListener);
228 mGlobalListenersAdded = true;
229 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700230 }
231
232 @Override
233 protected void onWindowVisibilityChanged(int visibility) {
234 super.onWindowVisibilityChanged(visibility);
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700235 mWindowVisibility = visibility == VISIBLE;
236 mRequestedVisible = mWindowVisibility && mViewVisibility;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700237 updateWindow(false, false);
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700238 }
239
240 @Override
241 public void setVisibility(int visibility) {
242 super.setVisibility(visibility);
243 mViewVisibility = visibility == VISIBLE;
Mathias Agopiancbeb3322012-05-12 19:57:07 -0700244 boolean newRequestedVisible = mWindowVisibility && mViewVisibility;
245 if (newRequestedVisible != mRequestedVisible) {
246 // our base class (View) invalidates the layout only when
247 // we go from/to the GONE state. However, SurfaceView needs
248 // to request a re-layout when the visibility changes at all.
249 // This is needed because the transparent region is computed
250 // as part of the layout phase, and it changes (obviously) when
251 // the visibility changes.
252 requestLayout();
253 }
254 mRequestedVisible = newRequestedVisible;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700255 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700256 }
Romain Guyafc3e112010-06-07 17:04:33 -0700257
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700258 @Override
259 protected void onDetachedFromWindow() {
Romain Guy01d5edc2011-01-28 11:28:53 -0800260 if (mGlobalListenersAdded) {
261 ViewTreeObserver observer = getViewTreeObserver();
262 observer.removeOnScrollChangedListener(mScrollChangedListener);
263 observer.removeOnPreDrawListener(mDrawListener);
264 mGlobalListenersAdded = false;
265 }
266
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700267 mRequestedVisible = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700268 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700269 mHaveFrame = false;
270 if (mWindow != null) {
271 try {
272 mSession.remove(mWindow);
273 } catch (RemoteException ex) {
Romain Guy01d5edc2011-01-28 11:28:53 -0800274 // Not much we can do here...
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700275 }
276 mWindow = null;
277 }
278 mSession = null;
279 mLayout.token = null;
280
281 super.onDetachedFromWindow();
282 }
283
284 @Override
285 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Dianne Hackborn189ee182010-12-02 21:48:53 -0800286 int width = mRequestedWidth >= 0
287 ? resolveSizeAndState(mRequestedWidth, widthMeasureSpec, 0)
288 : getDefaultSize(0, widthMeasureSpec);
289 int height = mRequestedHeight >= 0
290 ? resolveSizeAndState(mRequestedHeight, heightMeasureSpec, 0)
291 : getDefaultSize(0, heightMeasureSpec);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700292 setMeasuredDimension(width, height);
293 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700294
Mathias Agopianef115302010-10-04 20:15:08 -0700295 /** @hide */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700296 @Override
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700297 protected boolean setFrame(int left, int top, int right, int bottom) {
298 boolean result = super.setFrame(left, top, right, bottom);
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700299 updateWindow(false, false);
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700300 return result;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700301 }
302
303 @Override
304 public boolean gatherTransparentRegion(Region region) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700305 if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
306 return super.gatherTransparentRegion(region);
307 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700308
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700309 boolean opaque = true;
Dianne Hackborn4702a852012-08-17 15:18:29 -0700310 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700311 // this view draws, remove it from the transparent region
312 opaque = super.gatherTransparentRegion(region);
313 } else if (region != null) {
314 int w = getWidth();
315 int h = getHeight();
316 if (w>0 && h>0) {
317 getLocationInWindow(mLocation);
318 // otherwise, punch a hole in the whole hierarchy
319 int l = mLocation[0];
320 int t = mLocation[1];
321 region.op(l, t, l+w, t+h, Region.Op.UNION);
322 }
323 }
324 if (PixelFormat.formatHasAlpha(mRequestedFormat)) {
325 opaque = false;
326 }
327 return opaque;
328 }
329
330 @Override
331 public void draw(Canvas canvas) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700332 if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
333 // draw() is not called when SKIP_DRAW is set
Dianne Hackborn4702a852012-08-17 15:18:29 -0700334 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700335 // punch a whole in the view-hierarchy below us
336 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
337 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700338 }
339 super.draw(canvas);
340 }
341
342 @Override
343 protected void dispatchDraw(Canvas canvas) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700344 if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
345 // if SKIP_DRAW is cleared, draw() has already punched a hole
Dianne Hackborn4702a852012-08-17 15:18:29 -0700346 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700347 // punch a whole in the view-hierarchy below us
348 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
349 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700350 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700351 super.dispatchDraw(canvas);
352 }
353
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700354 /**
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700355 * Control whether the surface view's surface is placed on top of another
356 * regular surface view in the window (but still behind the window itself).
357 * This is typically used to place overlays on top of an underlying media
358 * surface view.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700359 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700360 * <p>Note that this must be set before the surface view's containing
361 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700362 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700363 * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
364 */
365 public void setZOrderMediaOverlay(boolean isMediaOverlay) {
366 mWindowType = isMediaOverlay
367 ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
368 : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
369 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700370
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700371 /**
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700372 * Control whether the surface view's surface is placed on top of its
373 * window. Normally it is placed behind the window, to allow it to
374 * (for the most part) appear to composite with the views in the
375 * hierarchy. By setting this, you cause it to be placed above the
376 * window. This means that none of the contents of the window this
377 * SurfaceView is in will be visible on top of its surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700378 *
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700379 * <p>Note that this must be set before the surface view's containing
380 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700381 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700382 * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700383 */
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700384 public void setZOrderOnTop(boolean onTop) {
Derek Sollenbergerecde72f2010-03-01 13:44:42 -0500385 if (onTop) {
386 mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
387 // ensures the surface is placed below the IME
388 mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
389 } else {
390 mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
391 mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
392 }
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700393 }
Jeff Brownf0681b32012-10-23 17:35:57 -0700394
395 /**
396 * Control whether the surface view's content should be treated as secure,
397 * preventing it from appearing in screenshots or from being viewed on
398 * non-secure displays.
399 *
400 * <p>Note that this must be set before the surface view's containing
401 * window is attached to the window manager.
402 *
403 * <p>See {@link android.view.Display#FLAG_SECURE} for details.
404 *
405 * @param isSecure True if the surface view is secure.
406 */
407 public void setSecure(boolean isSecure) {
408 if (isSecure) {
409 mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
410 } else {
411 mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
412 }
413 }
414
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700415 /**
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700416 * Hack to allow special layering of windows. The type is one of the
417 * types in WindowManager.LayoutParams. This is a hack so:
418 * @hide
419 */
420 public void setWindowType(int type) {
421 mWindowType = type;
422 }
Mitsuru Oshima34bf2ee2009-07-17 09:57:28 -0700423
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700424 private void updateWindow(boolean force, boolean redrawNeeded) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700425 if (!mHaveFrame) {
426 return;
427 }
Jeff Browna175a5b2012-02-15 19:18:31 -0800428 ViewRootImpl viewRoot = getViewRootImpl();
Joe Onorato168173a2009-08-12 21:40:29 -0700429 if (viewRoot != null) {
430 mTranslator = viewRoot.mTranslator;
431 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700432
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700433 if (mTranslator != null) {
434 mSurface.setCompatibilityTranslator(mTranslator);
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700435 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700436
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700437 int myWidth = mRequestedWidth;
438 if (myWidth <= 0) myWidth = getWidth();
439 int myHeight = mRequestedHeight;
440 if (myHeight <= 0) myHeight = getHeight();
Mitsuru Oshima001a6e522009-05-11 21:14:03 -0700441
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700442 getLocationInWindow(mLocation);
443 final boolean creating = mWindow == null;
444 final boolean formatChanged = mFormat != mRequestedFormat;
445 final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800446 final boolean visibleChanged = mVisible != mRequestedVisible;
Mathias Agopiand2112302010-12-07 19:38:17 -0800447
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700448 if (force || creating || formatChanged || sizeChanged || visibleChanged
Mathias Agopiand2112302010-12-07 19:38:17 -0800449 || mLeft != mLocation[0] || mTop != mLocation[1]
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700450 || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700451
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800452 if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700453 + " format=" + formatChanged + " size=" + sizeChanged
454 + " visible=" + visibleChanged
455 + " left=" + (mLeft != mLocation[0])
456 + " top=" + (mTop != mLocation[1]));
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700457
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700458 try {
459 final boolean visible = mVisible = mRequestedVisible;
460 mLeft = mLocation[0];
461 mTop = mLocation[1];
462 mWidth = myWidth;
463 mHeight = myHeight;
464 mFormat = mRequestedFormat;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700465
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700466 // Scaling/Translate window's layout here because mLayout is not used elsewhere.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700467
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700468 // Places the window relative
469 mLayout.x = mLeft;
470 mLayout.y = mTop;
471 mLayout.width = getWidth();
472 mLayout.height = getHeight();
473 if (mTranslator != null) {
474 mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
475 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700476
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700477 mLayout.format = mRequestedFormat;
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700478 mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
479 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
480 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700481 | WindowManager.LayoutParams.FLAG_SCALED
482 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
483 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
484 ;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -0700485 if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
Adam Lesinski95c42972013-10-02 10:13:27 -0700486 mLayout.privateFlags |=
487 WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -0700488 }
Dianne Hackborn1c5383c2013-04-15 15:07:21 -0700489 mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700490
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700491 if (mWindow == null) {
Jeff Brown8d0243a2012-09-24 15:01:47 -0700492 Display display = getDisplay();
Jon Larimer9bdf5762009-01-02 18:55:15 -0500493 mWindow = new MyWindow(this);
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700494 mLayout.type = mWindowType;
Fabrice Di Meglioaac0d4e2012-07-19 19:21:26 -0700495 mLayout.gravity = Gravity.START|Gravity.TOP;
Craig Mautner6881a102012-07-27 13:04:51 -0700496 mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
Jeff Brown8d0243a2012-09-24 15:01:47 -0700497 mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700498 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700499
Dianne Hackborn726426e2010-03-31 22:04:36 -0700500 boolean realSizeChanged;
501 boolean reportDrawNeeded;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800502
503 int relayoutResult;
504
Dianne Hackborn726426e2010-03-31 22:04:36 -0700505 mSurfaceLock.lock();
506 try {
507 mUpdateWindowNeeded = false;
508 reportDrawNeeded = mReportDrawNeeded;
509 mReportDrawNeeded = false;
510 mDrawingStopped = !visible;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700511
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800512 if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
513
514 relayoutResult = mSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700515 mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800516 visible ? VISIBLE : GONE,
Jeff Brown98365d72012-08-19 20:30:52 -0700517 WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800518 mWinFrame, mOverscanInsets, mContentInsets,
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800519 mVisibleInsets, mConfiguration, mNewSurface);
Jeff Brown98365d72012-08-19 20:30:52 -0700520 if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700521 mReportDrawNeeded = true;
522 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800523
524 if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
Dianne Hackborn726426e2010-03-31 22:04:36 -0700525 + ", vis=" + visible + ", frame=" + mWinFrame);
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800526
Dianne Hackborn726426e2010-03-31 22:04:36 -0700527 mSurfaceFrame.left = 0;
528 mSurfaceFrame.top = 0;
529 if (mTranslator == null) {
530 mSurfaceFrame.right = mWinFrame.width();
531 mSurfaceFrame.bottom = mWinFrame.height();
532 } else {
533 float appInvertedScale = mTranslator.applicationInvertedScale;
534 mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
535 mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
536 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700537
Dianne Hackborn726426e2010-03-31 22:04:36 -0700538 final int surfaceWidth = mSurfaceFrame.right;
539 final int surfaceHeight = mSurfaceFrame.bottom;
540 realSizeChanged = mLastSurfaceWidth != surfaceWidth
541 || mLastSurfaceHeight != surfaceHeight;
542 mLastSurfaceWidth = surfaceWidth;
543 mLastSurfaceHeight = surfaceHeight;
544 } finally {
545 mSurfaceLock.unlock();
Mitsuru Oshima589cebe2009-07-22 20:38:58 -0700546 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700547
548 try {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700549 redrawNeeded |= creating | reportDrawNeeded;
550
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800551 SurfaceHolder.Callback callbacks[] = null;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700552
Jeff Brown98365d72012-08-19 20:30:52 -0700553 final boolean surfaceChanged = (relayoutResult
554 & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800555 if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
556 mSurfaceCreated = false;
557 if (mSurface.isValid()) {
558 if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
559 callbacks = getSurfaceCallbacks();
560 for (SurfaceHolder.Callback c : callbacks) {
561 c.surfaceDestroyed(mSurfaceHolder);
562 }
Mitsuru Oshima3d914922009-05-13 22:29:15 -0700563 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800564 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700565
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800566 mSurface.transferFrom(mNewSurface);
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800567
Andreas Röhlf750b8c2012-07-02 13:06:26 +0200568 if (visible && mSurface.isValid()) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800569 if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
570 mSurfaceCreated = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700571 mIsCreating = true;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800572 if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
573 if (callbacks == null) {
574 callbacks = getSurfaceCallbacks();
575 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700576 for (SurfaceHolder.Callback c : callbacks) {
577 c.surfaceCreated(mSurfaceHolder);
578 }
579 }
580 if (creating || formatChanged || sizeChanged
Dianne Hackborn726426e2010-03-31 22:04:36 -0700581 || visibleChanged || realSizeChanged) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800582 if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
583 + " w=" + myWidth + " h=" + myHeight);
584 if (callbacks == null) {
585 callbacks = getSurfaceCallbacks();
586 }
Dianne Hackborn251fd432010-07-14 16:56:31 -0700587 for (SurfaceHolder.Callback c : callbacks) {
588 c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
589 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700590 }
591 if (redrawNeeded) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800592 if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
593 if (callbacks == null) {
594 callbacks = getSurfaceCallbacks();
595 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700596 for (SurfaceHolder.Callback c : callbacks) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700597 if (c instanceof SurfaceHolder.Callback2) {
598 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
599 mSurfaceHolder);
600 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700601 }
602 }
603 }
604 } finally {
605 mIsCreating = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700606 if (redrawNeeded) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800607 if (DEBUG) Log.i(TAG, "finishedDrawing");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700608 mSession.finishDrawing(mWindow);
609 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800610 mSession.performDeferredDestroy(mWindow);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700611 }
612 } catch (RemoteException ex) {
613 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800614 if (DEBUG) Log.v(
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700615 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
616 " w=" + mLayout.width + " h=" + mLayout.height +
617 ", frame=" + mSurfaceFrame);
618 }
619 }
620
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800621 private SurfaceHolder.Callback[] getSurfaceCallbacks() {
622 SurfaceHolder.Callback callbacks[];
623 synchronized (mCallbacks) {
624 callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
625 mCallbacks.toArray(callbacks);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700626 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800627 return callbacks;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700628 }
629
630 void handleGetNewSurface() {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700631 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700632 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800633
Derek Sollenberger7179b812010-03-22 13:41:20 -0400634 /**
635 * Check to see if the surface has fixed size dimensions or if the surface's
636 * dimensions are dimensions are dependent on its current layout.
637 *
638 * @return true if the surface has dimensions that are fixed in size
639 * @hide
640 */
641 public boolean isFixedSize() {
642 return (mRequestedWidth != -1 || mRequestedHeight != -1);
643 }
644
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700645 private static class MyWindow extends BaseIWindow {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700646 private final WeakReference<SurfaceView> mSurfaceView;
Jon Larimer9bdf5762009-01-02 18:55:15 -0500647
648 public MyWindow(SurfaceView surfaceView) {
649 mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
650 }
651
Craig Mautner656e3af2012-09-06 15:04:22 -0700652 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800653 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800654 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500655 SurfaceView surfaceView = mSurfaceView.get();
656 if (surfaceView != null) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800657 if (DEBUG) Log.v(
Craig Mautner656e3af2012-09-06 15:04:22 -0700658 "SurfaceView", surfaceView + " got resized: w=" + frame.width()
659 + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
Dianne Hackborn726426e2010-03-31 22:04:36 -0700660 surfaceView.mSurfaceLock.lock();
661 try {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500662 if (reportDraw) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700663 surfaceView.mUpdateWindowNeeded = true;
664 surfaceView.mReportDrawNeeded = true;
665 surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
Craig Mautner656e3af2012-09-06 15:04:22 -0700666 } else if (surfaceView.mWinFrame.width() != frame.width()
667 || surfaceView.mWinFrame.height() != frame.height()) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700668 surfaceView.mUpdateWindowNeeded = true;
669 surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700670 }
Dianne Hackborn726426e2010-03-31 22:04:36 -0700671 } finally {
672 surfaceView.mSurfaceLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700673 }
674 }
675 }
676
Igor Murashkina86ab6402013-08-30 12:58:36 -0700677 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700678 public void dispatchAppVisibility(boolean visible) {
679 // The point of SurfaceView is to let the app control the surface.
680 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800681
Igor Murashkina86ab6402013-08-30 12:58:36 -0700682 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700683 public void dispatchGetNewSurface() {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500684 SurfaceView surfaceView = mSurfaceView.get();
685 if (surfaceView != null) {
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800686 Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
687 surfaceView.mHandler.sendMessage(msg);
Jon Larimer9bdf5762009-01-02 18:55:15 -0500688 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700689 }
690
Igor Murashkina86ab6402013-08-30 12:58:36 -0700691 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700692 public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
693 Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
694 }
695
Igor Murashkina86ab6402013-08-30 12:58:36 -0700696 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700697 public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
698 }
699
700 int mCurWidth = -1;
701 int mCurHeight = -1;
702 }
703
Igor Murashkina86ab6402013-08-30 12:58:36 -0700704 private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
705
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700706 private static final String LOG_TAG = "SurfaceHolder";
Igor Murashkina86ab6402013-08-30 12:58:36 -0700707
708 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700709 public boolean isCreating() {
710 return mIsCreating;
711 }
712
Igor Murashkina86ab6402013-08-30 12:58:36 -0700713 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700714 public void addCallback(Callback callback) {
715 synchronized (mCallbacks) {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700716 // This is a linear search, but in practice we'll
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700717 // have only a couple callbacks, so it doesn't matter.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700718 if (mCallbacks.contains(callback) == false) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700719 mCallbacks.add(callback);
720 }
721 }
722 }
723
Igor Murashkina86ab6402013-08-30 12:58:36 -0700724 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700725 public void removeCallback(Callback callback) {
726 synchronized (mCallbacks) {
727 mCallbacks.remove(callback);
728 }
729 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700730
731 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700732 public void setFixedSize(int width, int height) {
733 if (mRequestedWidth != width || mRequestedHeight != height) {
734 mRequestedWidth = width;
735 mRequestedHeight = height;
736 requestLayout();
737 }
738 }
739
Igor Murashkina86ab6402013-08-30 12:58:36 -0700740 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700741 public void setSizeFromLayout() {
742 if (mRequestedWidth != -1 || mRequestedHeight != -1) {
743 mRequestedWidth = mRequestedHeight = -1;
744 requestLayout();
745 }
746 }
747
Igor Murashkina86ab6402013-08-30 12:58:36 -0700748 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700749 public void setFormat(int format) {
Mathias Agopian2d468c52010-06-14 21:50:48 -0700750
751 // for backward compatibility reason, OPAQUE always
752 // means 565 for SurfaceView
753 if (format == PixelFormat.OPAQUE)
754 format = PixelFormat.RGB_565;
755
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700756 mRequestedFormat = format;
757 if (mWindow != null) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700758 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700759 }
760 }
761
Mathias Agopiand2112302010-12-07 19:38:17 -0800762 /**
763 * @deprecated setType is now ignored.
764 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700765 @Override
Mathias Agopiand2112302010-12-07 19:38:17 -0800766 @Deprecated
767 public void setType(int type) { }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700768
Igor Murashkina86ab6402013-08-30 12:58:36 -0700769 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700770 public void setKeepScreenOn(boolean screenOn) {
771 Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
772 msg.arg1 = screenOn ? 1 : 0;
773 mHandler.sendMessage(msg);
774 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700775
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700776 /**
777 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
778 *
779 * After drawing into the provided {@link Canvas}, the caller must
780 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
781 *
782 * The caller must redraw the entire surface.
783 * @return A canvas for drawing into the surface.
784 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700785 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700786 public Canvas lockCanvas() {
787 return internalLockCanvas(null);
788 }
789
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700790 /**
791 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
792 *
793 * After drawing into the provided {@link Canvas}, the caller must
794 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
795 *
796 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
797 * to redraw. This function may choose to expand the dirty rectangle if for example
798 * the surface has been resized or if the previous contents of the surface were
799 * not available. The caller must redraw the entire dirty region as represented
800 * by the contents of the inOutDirty rectangle upon return from this function.
801 * The caller may also pass <code>null</code> instead, in the case where the
802 * entire surface should be redrawn.
803 * @return A canvas for drawing into the surface.
804 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700805 @Override
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700806 public Canvas lockCanvas(Rect inOutDirty) {
807 return internalLockCanvas(inOutDirty);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700808 }
809
810 private final Canvas internalLockCanvas(Rect dirty) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700811 mSurfaceLock.lock();
812
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800813 if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700814 + mDrawingStopped + ", win=" + mWindow);
815
816 Canvas c = null;
817 if (!mDrawingStopped && mWindow != null) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700818 try {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800819 c = mSurface.lockCanvas(dirty);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700820 } catch (Exception e) {
821 Log.e(LOG_TAG, "Exception locking surface", e);
822 }
823 }
824
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800825 if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700826 if (c != null) {
827 mLastLockTime = SystemClock.uptimeMillis();
828 return c;
829 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700830
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700831 // If the Surface is not ready to be drawn, then return null,
832 // but throttle calls to this function so it isn't called more
833 // than every 100ms.
834 long now = SystemClock.uptimeMillis();
835 long nextTime = mLastLockTime + 100;
836 if (nextTime > now) {
837 try {
838 Thread.sleep(nextTime-now);
839 } catch (InterruptedException e) {
840 }
841 now = SystemClock.uptimeMillis();
842 }
843 mLastLockTime = now;
844 mSurfaceLock.unlock();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700845
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700846 return null;
847 }
848
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700849 /**
850 * Posts the new contents of the {@link Canvas} to the surface and
851 * releases the {@link Canvas}.
852 *
853 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
854 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700855 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700856 public void unlockCanvasAndPost(Canvas canvas) {
857 mSurface.unlockCanvasAndPost(canvas);
858 mSurfaceLock.unlock();
859 }
860
Igor Murashkina86ab6402013-08-30 12:58:36 -0700861 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700862 public Surface getSurface() {
863 return mSurface;
864 }
865
Igor Murashkina86ab6402013-08-30 12:58:36 -0700866 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700867 public Rect getSurfaceFrame() {
868 return mSurfaceFrame;
869 }
870 };
871}