blob: 1e4b29f7a064c19ea3169964510123703a441e44 [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
191 public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
192 super(context, attrs, defStyle);
Mathias Agopiand6ddcb72010-05-24 19:00:08 -0700193 init();
194 }
195
196 private void init() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700197 setWillNotDraw(true);
198 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700199
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700200 /**
201 * Return the SurfaceHolder providing access and control over this
202 * SurfaceView's underlying surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700203 *
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700204 * @return SurfaceHolder The holder of the surface.
205 */
206 public SurfaceHolder getHolder() {
207 return mSurfaceHolder;
208 }
209
210 @Override
211 protected void onAttachedToWindow() {
212 super.onAttachedToWindow();
213 mParent.requestTransparentRegion(this);
214 mSession = getWindowSession();
215 mLayout.token = getWindowToken();
216 mLayout.setTitle("SurfaceView");
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700217 mViewVisibility = getVisibility() == VISIBLE;
Romain Guy01d5edc2011-01-28 11:28:53 -0800218
219 if (!mGlobalListenersAdded) {
220 ViewTreeObserver observer = getViewTreeObserver();
221 observer.addOnScrollChangedListener(mScrollChangedListener);
222 observer.addOnPreDrawListener(mDrawListener);
223 mGlobalListenersAdded = true;
224 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700225 }
226
227 @Override
228 protected void onWindowVisibilityChanged(int visibility) {
229 super.onWindowVisibilityChanged(visibility);
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700230 mWindowVisibility = visibility == VISIBLE;
231 mRequestedVisible = mWindowVisibility && mViewVisibility;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700232 updateWindow(false, false);
Mathias Agopian6b7f1a62009-09-09 18:32:34 -0700233 }
234
235 @Override
236 public void setVisibility(int visibility) {
237 super.setVisibility(visibility);
238 mViewVisibility = visibility == VISIBLE;
Mathias Agopiancbeb3322012-05-12 19:57:07 -0700239 boolean newRequestedVisible = mWindowVisibility && mViewVisibility;
240 if (newRequestedVisible != mRequestedVisible) {
241 // our base class (View) invalidates the layout only when
242 // we go from/to the GONE state. However, SurfaceView needs
243 // to request a re-layout when the visibility changes at all.
244 // This is needed because the transparent region is computed
245 // as part of the layout phase, and it changes (obviously) when
246 // the visibility changes.
247 requestLayout();
248 }
249 mRequestedVisible = newRequestedVisible;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700250 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700251 }
Romain Guyafc3e112010-06-07 17:04:33 -0700252
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700253 @Override
254 protected void onDetachedFromWindow() {
Romain Guy01d5edc2011-01-28 11:28:53 -0800255 if (mGlobalListenersAdded) {
256 ViewTreeObserver observer = getViewTreeObserver();
257 observer.removeOnScrollChangedListener(mScrollChangedListener);
258 observer.removeOnPreDrawListener(mDrawListener);
259 mGlobalListenersAdded = false;
260 }
261
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700262 mRequestedVisible = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700263 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700264 mHaveFrame = false;
265 if (mWindow != null) {
266 try {
267 mSession.remove(mWindow);
268 } catch (RemoteException ex) {
Romain Guy01d5edc2011-01-28 11:28:53 -0800269 // Not much we can do here...
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700270 }
271 mWindow = null;
272 }
273 mSession = null;
274 mLayout.token = null;
275
276 super.onDetachedFromWindow();
277 }
278
279 @Override
280 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Dianne Hackborn189ee182010-12-02 21:48:53 -0800281 int width = mRequestedWidth >= 0
282 ? resolveSizeAndState(mRequestedWidth, widthMeasureSpec, 0)
283 : getDefaultSize(0, widthMeasureSpec);
284 int height = mRequestedHeight >= 0
285 ? resolveSizeAndState(mRequestedHeight, heightMeasureSpec, 0)
286 : getDefaultSize(0, heightMeasureSpec);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700287 setMeasuredDimension(width, height);
288 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700289
Mathias Agopianef115302010-10-04 20:15:08 -0700290 /** @hide */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700291 @Override
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700292 protected boolean setFrame(int left, int top, int right, int bottom) {
293 boolean result = super.setFrame(left, top, right, bottom);
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700294 updateWindow(false, false);
Mathias Agopian995bb9d2010-10-04 17:13:15 -0700295 return result;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700296 }
297
298 @Override
299 public boolean gatherTransparentRegion(Region region) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700300 if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
301 return super.gatherTransparentRegion(region);
302 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700303
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700304 boolean opaque = true;
Dianne Hackborn4702a852012-08-17 15:18:29 -0700305 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700306 // this view draws, remove it from the transparent region
307 opaque = super.gatherTransparentRegion(region);
308 } else if (region != null) {
309 int w = getWidth();
310 int h = getHeight();
311 if (w>0 && h>0) {
312 getLocationInWindow(mLocation);
313 // otherwise, punch a hole in the whole hierarchy
314 int l = mLocation[0];
315 int t = mLocation[1];
316 region.op(l, t, l+w, t+h, Region.Op.UNION);
317 }
318 }
319 if (PixelFormat.formatHasAlpha(mRequestedFormat)) {
320 opaque = false;
321 }
322 return opaque;
323 }
324
325 @Override
326 public void draw(Canvas canvas) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700327 if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
328 // draw() is not called when SKIP_DRAW is set
Dianne Hackborn4702a852012-08-17 15:18:29 -0700329 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700330 // punch a whole in the view-hierarchy below us
331 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
332 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700333 }
334 super.draw(canvas);
335 }
336
337 @Override
338 protected void dispatchDraw(Canvas canvas) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700339 if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
340 // if SKIP_DRAW is cleared, draw() has already punched a hole
Dianne Hackborn4702a852012-08-17 15:18:29 -0700341 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700342 // punch a whole in the view-hierarchy below us
343 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
344 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700345 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700346 super.dispatchDraw(canvas);
347 }
348
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700349 /**
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700350 * Control whether the surface view's surface is placed on top of another
351 * regular surface view in the window (but still behind the window itself).
352 * This is typically used to place overlays on top of an underlying media
353 * surface view.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700354 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700355 * <p>Note that this must be set before the surface view's containing
356 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700357 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700358 * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
359 */
360 public void setZOrderMediaOverlay(boolean isMediaOverlay) {
361 mWindowType = isMediaOverlay
362 ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
363 : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
364 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700365
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700366 /**
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700367 * Control whether the surface view's surface is placed on top of its
368 * window. Normally it is placed behind the window, to allow it to
369 * (for the most part) appear to composite with the views in the
370 * hierarchy. By setting this, you cause it to be placed above the
371 * window. This means that none of the contents of the window this
372 * SurfaceView is in will be visible on top of its surface.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700373 *
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700374 * <p>Note that this must be set before the surface view's containing
375 * window is attached to the window manager.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700376 *
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700377 * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700378 */
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -0700379 public void setZOrderOnTop(boolean onTop) {
Derek Sollenbergerecde72f2010-03-01 13:44:42 -0500380 if (onTop) {
381 mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
382 // ensures the surface is placed below the IME
383 mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
384 } else {
385 mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
386 mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
387 }
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700388 }
Jeff Brownf0681b32012-10-23 17:35:57 -0700389
390 /**
391 * Control whether the surface view's content should be treated as secure,
392 * preventing it from appearing in screenshots or from being viewed on
393 * non-secure displays.
394 *
395 * <p>Note that this must be set before the surface view's containing
396 * window is attached to the window manager.
397 *
398 * <p>See {@link android.view.Display#FLAG_SECURE} for details.
399 *
400 * @param isSecure True if the surface view is secure.
401 */
402 public void setSecure(boolean isSecure) {
403 if (isSecure) {
404 mLayout.flags |= WindowManager.LayoutParams.FLAG_SECURE;
405 } else {
406 mLayout.flags &= ~WindowManager.LayoutParams.FLAG_SECURE;
407 }
408 }
409
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700410 /**
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700411 * Hack to allow special layering of windows. The type is one of the
412 * types in WindowManager.LayoutParams. This is a hack so:
413 * @hide
414 */
415 public void setWindowType(int type) {
416 mWindowType = type;
417 }
Mitsuru Oshima34bf2ee2009-07-17 09:57:28 -0700418
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700419 private void updateWindow(boolean force, boolean redrawNeeded) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700420 if (!mHaveFrame) {
421 return;
422 }
Jeff Browna175a5b2012-02-15 19:18:31 -0800423 ViewRootImpl viewRoot = getViewRootImpl();
Joe Onorato168173a2009-08-12 21:40:29 -0700424 if (viewRoot != null) {
425 mTranslator = viewRoot.mTranslator;
426 }
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700427
Dianne Hackborn5be8de32011-05-24 18:11:57 -0700428 if (mTranslator != null) {
429 mSurface.setCompatibilityTranslator(mTranslator);
Mitsuru Oshima38ed7d772009-07-21 14:39:34 -0700430 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700431
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700432 int myWidth = mRequestedWidth;
433 if (myWidth <= 0) myWidth = getWidth();
434 int myHeight = mRequestedHeight;
435 if (myHeight <= 0) myHeight = getHeight();
Mitsuru Oshima001a6e522009-05-11 21:14:03 -0700436
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700437 getLocationInWindow(mLocation);
438 final boolean creating = mWindow == null;
439 final boolean formatChanged = mFormat != mRequestedFormat;
440 final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800441 final boolean visibleChanged = mVisible != mRequestedVisible;
Mathias Agopiand2112302010-12-07 19:38:17 -0800442
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700443 if (force || creating || formatChanged || sizeChanged || visibleChanged
Mathias Agopiand2112302010-12-07 19:38:17 -0800444 || mLeft != mLocation[0] || mTop != mLocation[1]
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700445 || mUpdateWindowNeeded || mReportDrawNeeded || redrawNeeded) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700446
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800447 if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700448 + " format=" + formatChanged + " size=" + sizeChanged
449 + " visible=" + visibleChanged
450 + " left=" + (mLeft != mLocation[0])
451 + " top=" + (mTop != mLocation[1]));
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700452
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700453 try {
454 final boolean visible = mVisible = mRequestedVisible;
455 mLeft = mLocation[0];
456 mTop = mLocation[1];
457 mWidth = myWidth;
458 mHeight = myHeight;
459 mFormat = mRequestedFormat;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700460
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700461 // Scaling/Translate window's layout here because mLayout is not used elsewhere.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700462
Mitsuru Oshima64f59342009-06-21 00:03:11 -0700463 // Places the window relative
464 mLayout.x = mLeft;
465 mLayout.y = mTop;
466 mLayout.width = getWidth();
467 mLayout.height = getHeight();
468 if (mTranslator != null) {
469 mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
470 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700471
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700472 mLayout.format = mRequestedFormat;
Dianne Hackborn1cd403e2009-09-14 22:29:14 -0700473 mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
474 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
475 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700476 | WindowManager.LayoutParams.FLAG_SCALED
477 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
478 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
479 ;
Mitsuru Oshima841f13c2009-07-17 17:23:31 -0700480 if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {
481 mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
482 }
Dianne Hackborn1c5383c2013-04-15 15:07:21 -0700483 mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700484
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700485 if (mWindow == null) {
Jeff Brown8d0243a2012-09-24 15:01:47 -0700486 Display display = getDisplay();
Jon Larimer9bdf5762009-01-02 18:55:15 -0500487 mWindow = new MyWindow(this);
Dianne Hackbornc4d5d022009-05-21 17:32:42 -0700488 mLayout.type = mWindowType;
Fabrice Di Meglioaac0d4e2012-07-19 19:21:26 -0700489 mLayout.gravity = Gravity.START|Gravity.TOP;
Craig Mautner6881a102012-07-27 13:04:51 -0700490 mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
Jeff Brown8d0243a2012-09-24 15:01:47 -0700491 mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700492 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700493
Dianne Hackborn726426e2010-03-31 22:04:36 -0700494 boolean realSizeChanged;
495 boolean reportDrawNeeded;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800496
497 int relayoutResult;
498
Dianne Hackborn726426e2010-03-31 22:04:36 -0700499 mSurfaceLock.lock();
500 try {
501 mUpdateWindowNeeded = false;
502 reportDrawNeeded = mReportDrawNeeded;
503 mReportDrawNeeded = false;
504 mDrawingStopped = !visible;
Igor Murashkina86ab6402013-08-30 12:58:36 -0700505
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800506 if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
507
508 relayoutResult = mSession.relayout(
Dianne Hackborn9a230e02011-10-06 11:51:27 -0700509 mWindow, mWindow.mSeq, mLayout, mWidth, mHeight,
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800510 visible ? VISIBLE : GONE,
Jeff Brown98365d72012-08-19 20:30:52 -0700511 WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY,
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800512 mWinFrame, mOverscanInsets, mContentInsets,
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800513 mVisibleInsets, mConfiguration, mNewSurface);
Jeff Brown98365d72012-08-19 20:30:52 -0700514 if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700515 mReportDrawNeeded = true;
516 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800517
518 if (DEBUG) Log.i(TAG, "New surface: " + mNewSurface
Dianne Hackborn726426e2010-03-31 22:04:36 -0700519 + ", vis=" + visible + ", frame=" + mWinFrame);
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800520
Dianne Hackborn726426e2010-03-31 22:04:36 -0700521 mSurfaceFrame.left = 0;
522 mSurfaceFrame.top = 0;
523 if (mTranslator == null) {
524 mSurfaceFrame.right = mWinFrame.width();
525 mSurfaceFrame.bottom = mWinFrame.height();
526 } else {
527 float appInvertedScale = mTranslator.applicationInvertedScale;
528 mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
529 mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
530 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700531
Dianne Hackborn726426e2010-03-31 22:04:36 -0700532 final int surfaceWidth = mSurfaceFrame.right;
533 final int surfaceHeight = mSurfaceFrame.bottom;
534 realSizeChanged = mLastSurfaceWidth != surfaceWidth
535 || mLastSurfaceHeight != surfaceHeight;
536 mLastSurfaceWidth = surfaceWidth;
537 mLastSurfaceHeight = surfaceHeight;
538 } finally {
539 mSurfaceLock.unlock();
Mitsuru Oshima589cebe2009-07-22 20:38:58 -0700540 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700541
542 try {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700543 redrawNeeded |= creating | reportDrawNeeded;
544
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800545 SurfaceHolder.Callback callbacks[] = null;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700546
Jeff Brown98365d72012-08-19 20:30:52 -0700547 final boolean surfaceChanged = (relayoutResult
548 & WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED) != 0;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800549 if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) {
550 mSurfaceCreated = false;
551 if (mSurface.isValid()) {
552 if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceDestroyed");
553 callbacks = getSurfaceCallbacks();
554 for (SurfaceHolder.Callback c : callbacks) {
555 c.surfaceDestroyed(mSurfaceHolder);
556 }
Mitsuru Oshima3d914922009-05-13 22:29:15 -0700557 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800558 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700559
Dianne Hackborn61566cc2011-12-02 23:31:52 -0800560 mSurface.transferFrom(mNewSurface);
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800561
Andreas Röhlf750b8c2012-07-02 13:06:26 +0200562 if (visible && mSurface.isValid()) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800563 if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) {
564 mSurfaceCreated = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700565 mIsCreating = true;
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800566 if (DEBUG) Log.i(TAG, "visibleChanged -- surfaceCreated");
567 if (callbacks == null) {
568 callbacks = getSurfaceCallbacks();
569 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700570 for (SurfaceHolder.Callback c : callbacks) {
571 c.surfaceCreated(mSurfaceHolder);
572 }
573 }
574 if (creating || formatChanged || sizeChanged
Dianne Hackborn726426e2010-03-31 22:04:36 -0700575 || visibleChanged || realSizeChanged) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800576 if (DEBUG) Log.i(TAG, "surfaceChanged -- format=" + mFormat
577 + " w=" + myWidth + " h=" + myHeight);
578 if (callbacks == null) {
579 callbacks = getSurfaceCallbacks();
580 }
Dianne Hackborn251fd432010-07-14 16:56:31 -0700581 for (SurfaceHolder.Callback c : callbacks) {
582 c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);
583 }
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700584 }
585 if (redrawNeeded) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800586 if (DEBUG) Log.i(TAG, "surfaceRedrawNeeded");
587 if (callbacks == null) {
588 callbacks = getSurfaceCallbacks();
589 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700590 for (SurfaceHolder.Callback c : callbacks) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700591 if (c instanceof SurfaceHolder.Callback2) {
592 ((SurfaceHolder.Callback2)c).surfaceRedrawNeeded(
593 mSurfaceHolder);
594 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700595 }
596 }
597 }
598 } finally {
599 mIsCreating = false;
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700600 if (redrawNeeded) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800601 if (DEBUG) Log.i(TAG, "finishedDrawing");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700602 mSession.finishDrawing(mWindow);
603 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800604 mSession.performDeferredDestroy(mWindow);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700605 }
606 } catch (RemoteException ex) {
607 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800608 if (DEBUG) Log.v(
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700609 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +
610 " w=" + mLayout.width + " h=" + mLayout.height +
611 ", frame=" + mSurfaceFrame);
612 }
613 }
614
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800615 private SurfaceHolder.Callback[] getSurfaceCallbacks() {
616 SurfaceHolder.Callback callbacks[];
617 synchronized (mCallbacks) {
618 callbacks = new SurfaceHolder.Callback[mCallbacks.size()];
619 mCallbacks.toArray(callbacks);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700620 }
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800621 return callbacks;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700622 }
623
624 void handleGetNewSurface() {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700625 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700626 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800627
Derek Sollenberger7179b812010-03-22 13:41:20 -0400628 /**
629 * Check to see if the surface has fixed size dimensions or if the surface's
630 * dimensions are dimensions are dependent on its current layout.
631 *
632 * @return true if the surface has dimensions that are fixed in size
633 * @hide
634 */
635 public boolean isFixedSize() {
636 return (mRequestedWidth != -1 || mRequestedHeight != -1);
637 }
638
Dianne Hackborn72c82ab2009-08-11 21:13:54 -0700639 private static class MyWindow extends BaseIWindow {
Mitsuru Oshima8169dae2009-04-28 18:12:09 -0700640 private final WeakReference<SurfaceView> mSurfaceView;
Jon Larimer9bdf5762009-01-02 18:55:15 -0500641
642 public MyWindow(SurfaceView surfaceView) {
643 mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
644 }
645
Craig Mautner656e3af2012-09-06 15:04:22 -0700646 @Override
Dianne Hackbornc4aad012013-02-22 15:05:25 -0800647 public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800648 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500649 SurfaceView surfaceView = mSurfaceView.get();
650 if (surfaceView != null) {
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800651 if (DEBUG) Log.v(
Craig Mautner656e3af2012-09-06 15:04:22 -0700652 "SurfaceView", surfaceView + " got resized: w=" + frame.width()
653 + " h=" + frame.height() + ", cur w=" + mCurWidth + " h=" + mCurHeight);
Dianne Hackborn726426e2010-03-31 22:04:36 -0700654 surfaceView.mSurfaceLock.lock();
655 try {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500656 if (reportDraw) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700657 surfaceView.mUpdateWindowNeeded = true;
658 surfaceView.mReportDrawNeeded = true;
659 surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
Craig Mautner656e3af2012-09-06 15:04:22 -0700660 } else if (surfaceView.mWinFrame.width() != frame.width()
661 || surfaceView.mWinFrame.height() != frame.height()) {
Dianne Hackborn726426e2010-03-31 22:04:36 -0700662 surfaceView.mUpdateWindowNeeded = true;
663 surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700664 }
Dianne Hackborn726426e2010-03-31 22:04:36 -0700665 } finally {
666 surfaceView.mSurfaceLock.unlock();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700667 }
668 }
669 }
670
Igor Murashkina86ab6402013-08-30 12:58:36 -0700671 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700672 public void dispatchAppVisibility(boolean visible) {
673 // The point of SurfaceView is to let the app control the surface.
674 }
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800675
Igor Murashkina86ab6402013-08-30 12:58:36 -0700676 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700677 public void dispatchGetNewSurface() {
Jon Larimer9bdf5762009-01-02 18:55:15 -0500678 SurfaceView surfaceView = mSurfaceView.get();
679 if (surfaceView != null) {
The Android Open Source Projectb7986892009-01-09 17:51:23 -0800680 Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);
681 surfaceView.mHandler.sendMessage(msg);
Jon Larimer9bdf5762009-01-02 18:55:15 -0500682 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700683 }
684
Igor Murashkina86ab6402013-08-30 12:58:36 -0700685 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700686 public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
687 Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
688 }
689
Igor Murashkina86ab6402013-08-30 12:58:36 -0700690 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700691 public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
692 }
693
694 int mCurWidth = -1;
695 int mCurHeight = -1;
696 }
697
Igor Murashkina86ab6402013-08-30 12:58:36 -0700698 private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
699
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700700 private static final String LOG_TAG = "SurfaceHolder";
Igor Murashkina86ab6402013-08-30 12:58:36 -0700701
702 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700703 public boolean isCreating() {
704 return mIsCreating;
705 }
706
Igor Murashkina86ab6402013-08-30 12:58:36 -0700707 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700708 public void addCallback(Callback callback) {
709 synchronized (mCallbacks) {
Igor Murashkina86ab6402013-08-30 12:58:36 -0700710 // This is a linear search, but in practice we'll
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700711 // have only a couple callbacks, so it doesn't matter.
Igor Murashkina86ab6402013-08-30 12:58:36 -0700712 if (mCallbacks.contains(callback) == false) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700713 mCallbacks.add(callback);
714 }
715 }
716 }
717
Igor Murashkina86ab6402013-08-30 12:58:36 -0700718 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700719 public void removeCallback(Callback callback) {
720 synchronized (mCallbacks) {
721 mCallbacks.remove(callback);
722 }
723 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700724
725 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700726 public void setFixedSize(int width, int height) {
727 if (mRequestedWidth != width || mRequestedHeight != height) {
728 mRequestedWidth = width;
729 mRequestedHeight = height;
730 requestLayout();
731 }
732 }
733
Igor Murashkina86ab6402013-08-30 12:58:36 -0700734 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700735 public void setSizeFromLayout() {
736 if (mRequestedWidth != -1 || mRequestedHeight != -1) {
737 mRequestedWidth = mRequestedHeight = -1;
738 requestLayout();
739 }
740 }
741
Igor Murashkina86ab6402013-08-30 12:58:36 -0700742 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700743 public void setFormat(int format) {
Mathias Agopian2d468c52010-06-14 21:50:48 -0700744
745 // for backward compatibility reason, OPAQUE always
746 // means 565 for SurfaceView
747 if (format == PixelFormat.OPAQUE)
748 format = PixelFormat.RGB_565;
749
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700750 mRequestedFormat = format;
751 if (mWindow != null) {
Dianne Hackbornd76b67c2010-07-13 17:48:30 -0700752 updateWindow(false, false);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700753 }
754 }
755
Mathias Agopiand2112302010-12-07 19:38:17 -0800756 /**
757 * @deprecated setType is now ignored.
758 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700759 @Override
Mathias Agopiand2112302010-12-07 19:38:17 -0800760 @Deprecated
761 public void setType(int type) { }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700762
Igor Murashkina86ab6402013-08-30 12:58:36 -0700763 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700764 public void setKeepScreenOn(boolean screenOn) {
765 Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
766 msg.arg1 = screenOn ? 1 : 0;
767 mHandler.sendMessage(msg);
768 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700769
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700770 /**
771 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
772 *
773 * After drawing into the provided {@link Canvas}, the caller must
774 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
775 *
776 * The caller must redraw the entire surface.
777 * @return A canvas for drawing into the surface.
778 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700779 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700780 public Canvas lockCanvas() {
781 return internalLockCanvas(null);
782 }
783
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700784 /**
785 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface
786 *
787 * After drawing into the provided {@link Canvas}, the caller must
788 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
789 *
790 * @param inOutDirty A rectangle that represents the dirty region that the caller wants
791 * to redraw. This function may choose to expand the dirty rectangle if for example
792 * the surface has been resized or if the previous contents of the surface were
793 * not available. The caller must redraw the entire dirty region as represented
794 * by the contents of the inOutDirty rectangle upon return from this function.
795 * The caller may also pass <code>null</code> instead, in the case where the
796 * entire surface should be redrawn.
797 * @return A canvas for drawing into the surface.
798 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700799 @Override
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700800 public Canvas lockCanvas(Rect inOutDirty) {
801 return internalLockCanvas(inOutDirty);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700802 }
803
804 private final Canvas internalLockCanvas(Rect dirty) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700805 mSurfaceLock.lock();
806
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800807 if (DEBUG) Log.i(TAG, "Locking canvas... stopped="
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700808 + mDrawingStopped + ", win=" + mWindow);
809
810 Canvas c = null;
811 if (!mDrawingStopped && mWindow != null) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700812 try {
Jeff Brown30bc34f2011-01-25 12:56:56 -0800813 c = mSurface.lockCanvas(dirty);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700814 } catch (Exception e) {
815 Log.e(LOG_TAG, "Exception locking surface", e);
816 }
817 }
818
Dianne Hackborn6d05fd32011-11-19 14:36:15 -0800819 if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700820 if (c != null) {
821 mLastLockTime = SystemClock.uptimeMillis();
822 return c;
823 }
Igor Murashkina86ab6402013-08-30 12:58:36 -0700824
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700825 // If the Surface is not ready to be drawn, then return null,
826 // but throttle calls to this function so it isn't called more
827 // than every 100ms.
828 long now = SystemClock.uptimeMillis();
829 long nextTime = mLastLockTime + 100;
830 if (nextTime > now) {
831 try {
832 Thread.sleep(nextTime-now);
833 } catch (InterruptedException e) {
834 }
835 now = SystemClock.uptimeMillis();
836 }
837 mLastLockTime = now;
838 mSurfaceLock.unlock();
Igor Murashkina86ab6402013-08-30 12:58:36 -0700839
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700840 return null;
841 }
842
Mathias Agopian9ddf32a2013-04-17 15:04:47 -0700843 /**
844 * Posts the new contents of the {@link Canvas} to the surface and
845 * releases the {@link Canvas}.
846 *
847 * @param canvas The canvas previously obtained from {@link #lockCanvas}.
848 */
Igor Murashkina86ab6402013-08-30 12:58:36 -0700849 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700850 public void unlockCanvasAndPost(Canvas canvas) {
851 mSurface.unlockCanvasAndPost(canvas);
852 mSurfaceLock.unlock();
853 }
854
Igor Murashkina86ab6402013-08-30 12:58:36 -0700855 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700856 public Surface getSurface() {
857 return mSurface;
858 }
859
Igor Murashkina86ab6402013-08-30 12:58:36 -0700860 @Override
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700861 public Rect getSurfaceFrame() {
862 return mSurfaceFrame;
863 }
864 };
865}