SurfaceView(7)SurfaceView源码

代码:

  1 /* 
  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   
 17 package android.view;  
 18   
 19 import android.util.DisplayMetrics;  
 20 import com.android.internal.view.BaseIWindow;  
 21   
 22 import android.content.Context;  
 23 import android.content.res.Configuration;  
 24 import android.content.res.Resources;  
 25 import android.content.res.CompatibilityInfo.Translator;  
 26 import android.graphics.Canvas;  
 27 import android.graphics.PixelFormat;  
 28 import android.graphics.PorterDuff;  
 29 import android.graphics.Rect;  
 30 import android.graphics.Region;  
 31 import android.os.Handler;  
 32 import android.os.Message;  
 33 import android.os.RemoteException;  
 34 import android.os.SystemClock;  
 35 import android.os.ParcelFileDescriptor;  
 36 import android.util.AttributeSet;  
 37 import android.util.Config;  
 38 import android.util.Log;  
 39   
 40 import java.lang.ref.WeakReference;  
 41 import java.util.ArrayList;  
 42 import java.util.concurrent.locks.ReentrantLock;  
 43   
 44 /** 
 45  * Provides a dedicated drawing surface embedded inside of a view hierarchy. 
 46  * You can control the format of this surface and, if you like, its size; the 
 47  * SurfaceView takes care of placing the surface at the correct location on the 
 48  * screen 
 49  *  
 50  * <p>The surface is Z ordered so that it is behind the window holding its 
 51  * SurfaceView; the SurfaceView punches a hole in its window to allow its 
 52  * surface to be displayed.  The view hierarchy will take care of correctly 
 53  * compositing with the Surface any siblings of the SurfaceView that would 
 54  * normally appear on top of it.  This can be used to place overlays such as 
 55  * buttons on top of the Surface, though note however that it can have an 
 56  * impact on performance since a full alpha-blended composite will be performed 
 57  * each time the Surface changes. 
 58  *  
 59  * <p>Access to the underlying surface is provided via the SurfaceHolder interface, 
 60  * which can be retrieved by calling {@link #getHolder}. 
 61  *  
 62  * <p>The Surface will be created for you while the SurfaceView's window is 
 63  * visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated} 
 64  * and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the 
 65  * Surface is created and destroyed as the window is shown and hidden. 
 66  *  
 67  * <p>One of the purposes of this class is to provide a surface in which a 
 68  * secondary thread can render in to the screen.  If you are going to use it 
 69  * this way, you need to be aware of some threading semantics: 
 70  *  
 71  * <ul> 
 72  * <li> All SurfaceView and 
 73  * {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called 
 74  * from the thread running the SurfaceView's window (typically the main thread 
 75  * of the application).  They thus need to correctly synchronize with any 
 76  * state that is also touched by the drawing thread. 
 77  * <li> You must ensure that the drawing thread only touches the underlying 
 78  * Surface while it is valid -- between 
 79  * {@link SurfaceHolder.Callback#surfaceCreated SurfaceHolder.Callback.surfaceCreated()} 
 80  * and 
 81  * {@link SurfaceHolder.Callback#surfaceDestroyed SurfaceHolder.Callback.surfaceDestroyed()}. 
 82  * </ul> 
 83  */  
 84 public class SurfaceView extends View {  
 85     static private final String TAG = "SurfaceView";  
 86     static private final boolean DEBUG = false;  
 87     static private final boolean localLOGV = DEBUG ? true : Config.LOGV;  
 88   
 89     final ArrayList<SurfaceHolder.Callback> mCallbacks  
 90             = new ArrayList<SurfaceHolder.Callback>();  
 91   
 92     final int[] mLocation = new int[2];  
 93       
 94     final ReentrantLock mSurfaceLock = new ReentrantLock();  
 95     final Surface mSurface = new Surface();  
 96     boolean mDrawingStopped = true;  
 97   
 98     final WindowManager.LayoutParams mLayout  
 99             = new WindowManager.LayoutParams();  
100     IWindowSession mSession;  
101     MyWindow mWindow;  
102     final Rect mVisibleInsets = new Rect();  
103     final Rect mWinFrame = new Rect();  
104     final Rect mContentInsets = new Rect();  
105     final Configuration mConfiguration = new Configuration();  
106       
107     static final int KEEP_SCREEN_ON_MSG = 1;  
108     static final int GET_NEW_SURFACE_MSG = 2;  
109     static final int UPDATE_WINDOW_MSG = 3;  
110       
111     int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;  
112       
113     boolean mIsCreating = false;  
114   
115     final Handler mHandler = new Handler() {  
116         @Override  
117         public void handleMessage(Message msg) {  
118             switch (msg.what) {  
119                 case KEEP_SCREEN_ON_MSG: {  
120                     setKeepScreenOn(msg.arg1 != 0);  
121                 } break;  
122                 case GET_NEW_SURFACE_MSG: {  
123                     handleGetNewSurface();  
124                 } break;  
125                 case UPDATE_WINDOW_MSG: {  
126                     updateWindow(false);  
127                 } break;  
128             }  
129         }  
130     };  
131       
132     final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener  
133             = new ViewTreeObserver.OnScrollChangedListener() {  
134                     public void onScrollChanged() {  
135                         updateWindow(false);  
136                     }  
137             };  
138               
139     boolean mRequestedVisible = false;  
140     boolean mWindowVisibility = false;  
141     boolean mViewVisibility = false;  
142     int mRequestedWidth = -1;  
143     int mRequestedHeight = -1;  
144     int mRequestedFormat = PixelFormat.OPAQUE;  
145     int mRequestedType = -1;  
146   
147     boolean mHaveFrame = false;  
148     boolean mDestroyReportNeeded = false;  
149     boolean mNewSurfaceNeeded = false;  
150     long mLastLockTime = 0;  
151       
152     boolean mVisible = false;  
153     int mLeft = -1;  
154     int mTop = -1;  
155     int mWidth = -1;  
156     int mHeight = -1;  
157     int mFormat = -1;  
158     int mType = -1;  
159     final Rect mSurfaceFrame = new Rect();  
160     int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;  
161     boolean mUpdateWindowNeeded;  
162     boolean mReportDrawNeeded;  
163     private Translator mTranslator;  
164       
165     public SurfaceView(Context context) {  
166         super(context);  
167         setWillNotDraw(true);  
168     }  
169       
170     public SurfaceView(Context context, AttributeSet attrs) {  
171         super(context, attrs);  
172         setWillNotDraw(true);  
173     }  
174   
175     public SurfaceView(Context context, AttributeSet attrs, int defStyle) {  
176         super(context, attrs, defStyle);  
177         setWillNotDraw(true);  
178     }  
179       
180     /** 
181      * Return the SurfaceHolder providing access and control over this 
182      * SurfaceView's underlying surface. 
183      *  
184      * @return SurfaceHolder The holder of the surface. 
185      */  
186     public SurfaceHolder getHolder() {  
187         return mSurfaceHolder;  
188     }  
189   
190     @Override  
191     protected void onAttachedToWindow() {  
192         super.onAttachedToWindow();  
193         mParent.requestTransparentRegion(this);  
194         mSession = getWindowSession();  
195         mLayout.token = getWindowToken();  
196         mLayout.setTitle("SurfaceView");  
197         mViewVisibility = getVisibility() == VISIBLE;  
198         getViewTreeObserver().addOnScrollChangedListener(mScrollChangedListener);  
199     }  
200   
201     @Override  
202     protected void onWindowVisibilityChanged(int visibility) {  
203         super.onWindowVisibilityChanged(visibility);  
204         mWindowVisibility = visibility == VISIBLE;  
205         mRequestedVisible = mWindowVisibility && mViewVisibility;  
206         updateWindow(false);  
207     }  
208   
209     @Override  
210     public void setVisibility(int visibility) {  
211         super.setVisibility(visibility);  
212         mViewVisibility = visibility == VISIBLE;  
213         mRequestedVisible = mWindowVisibility && mViewVisibility;  
214         updateWindow(false);  
215     }  
216   
217     /** 
218      * This method is not intended for general use. It was created 
219      * temporarily to improve performance of 3D layers in Launcher 
220      * and should be removed and fixed properly. 
221      *  
222      * Do not call this method. Ever. 
223      *  
224      * @hide 
225      */  
226     protected void showSurface() {  
227         if (mSession != null) {  
228             updateWindow(true);  
229         }  
230     }  
231   
232     /** 
233      * This method is not intended for general use. It was created 
234      * temporarily to improve performance of 3D layers in Launcher 
235      * and should be removed and fixed properly. 
236      *  
237      * Do not call this method. Ever. 
238      *  
239      * @hide 
240      */  
241     protected void hideSurface() {  
242         if (mSession != null && mWindow != null) {  
243             mSurfaceLock.lock();  
244             try {  
245                 DisplayMetrics metrics = getResources().getDisplayMetrics();  
246                 mLayout.x = metrics.widthPixels * 3;  
247                 mSession.relayout(mWindow, mLayout, mWidth, mHeight, VISIBLE, false,  
248                         mWinFrame, mContentInsets, mVisibleInsets, mConfiguration, mSurface);  
249             } catch (RemoteException e) {  
250                 // Ignore  
251             } finally {  
252                 mSurfaceLock.unlock();  
253             }  
254         }  
255     }  
256       
257     @Override  
258     protected void onDetachedFromWindow() {  
259         getViewTreeObserver().removeOnScrollChangedListener(mScrollChangedListener);  
260         mRequestedVisible = false;  
261         updateWindow(false);  
262         mHaveFrame = false;  
263         if (mWindow != null) {  
264             try {  
265                 mSession.remove(mWindow);  
266             } catch (RemoteException ex) {  
267             }  
268             mWindow = null;  
269         }  
270         mSession = null;  
271         mLayout.token = null;  
272   
273         super.onDetachedFromWindow();  
274     }  
275   
276     @Override  
277     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
278         int width = getDefaultSize(mRequestedWidth, widthMeasureSpec);  
279         int height = getDefaultSize(mRequestedHeight, heightMeasureSpec);  
280         setMeasuredDimension(width, height);  
281     }  
282       
283     @Override  
284     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
285         super.onSizeChanged(w, h, oldw, oldh);  
286         updateWindow(false);  
287     }  
288   
289     @Override  
290     public boolean gatherTransparentRegion(Region region) {  
291         if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {  
292             return super.gatherTransparentRegion(region);  
293         }  
294           
295         boolean opaque = true;  
296         if ((mPrivateFlags & SKIP_DRAW) == 0) {  
297             // this view draws, remove it from the transparent region  
298             opaque = super.gatherTransparentRegion(region);  
299         } else if (region != null) {  
300             int w = getWidth();  
301             int h = getHeight();  
302             if (w>0 && h>0) {  
303                 getLocationInWindow(mLocation);  
304                 // otherwise, punch a hole in the whole hierarchy  
305                 int l = mLocation[0];  
306                 int t = mLocation[1];  
307                 region.op(l, t, l+w, t+h, Region.Op.UNION);  
308             }  
309         }  
310         if (PixelFormat.formatHasAlpha(mRequestedFormat)) {  
311             opaque = false;  
312         }  
313         return opaque;  
314     }  
315   
316     @Override  
317     public void draw(Canvas canvas) {  
318         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {  
319             // draw() is not called when SKIP_DRAW is set  
320             if ((mPrivateFlags & SKIP_DRAW) == 0) {  
321                 // punch a whole in the view-hierarchy below us  
322                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);  
323             }  
324         }  
325         super.draw(canvas);  
326     }  
327   
328     @Override  
329     protected void dispatchDraw(Canvas canvas) {  
330         if (mWindowType != WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {  
331             // if SKIP_DRAW is cleared, draw() has already punched a hole  
332             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {  
333                 // punch a whole in the view-hierarchy below us  
334                 canvas.drawColor(0, PorterDuff.Mode.CLEAR);  
335             }  
336         }  
337         // reposition ourselves where the surface is   
338         mHaveFrame = true;  
339         updateWindow(false);  
340         super.dispatchDraw(canvas);  
341     }  
342   
343     /** 
344      * Control whether the surface view's surface is placed on top of another 
345      * regular surface view in the window (but still behind the window itself). 
346      * This is typically used to place overlays on top of an underlying media 
347      * surface view. 
348      *  
349      * <p>Note that this must be set before the surface view's containing 
350      * window is attached to the window manager. 
351      *  
352      * <p>Calling this overrides any previous call to {@link #setZOrderOnTop}. 
353      */  
354     public void setZOrderMediaOverlay(boolean isMediaOverlay) {  
355         mWindowType = isMediaOverlay  
356                 ? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY  
357                 : WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;  
358     }  
359       
360     /** 
361      * Control whether the surface view's surface is placed on top of its 
362      * window.  Normally it is placed behind the window, to allow it to 
363      * (for the most part) appear to composite with the views in the 
364      * hierarchy.  By setting this, you cause it to be placed above the 
365      * window.  This means that none of the contents of the window this 
366      * SurfaceView is in will be visible on top of its surface. 
367      *  
368      * <p>Note that this must be set before the surface view's containing 
369      * window is attached to the window manager. 
370      *  
371      * <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}. 
372      */  
373     public void setZOrderOnTop(boolean onTop) {  
374         if (onTop) {  
375             mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;  
376             // ensures the surface is placed below the IME  
377             mLayout.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;  
378         } else {  
379             mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;  
380             mLayout.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;  
381         }  
382     }  
383       
384     /** 
385      * Hack to allow special layering of windows.  The type is one of the 
386      * types in WindowManager.LayoutParams.  This is a hack so: 
387      * @hide 
388      */  
389     public void setWindowType(int type) {  
390         mWindowType = type;  
391     }  
392   
393     private void updateWindow(boolean force) {  
394         if (!mHaveFrame) {  
395             return;  
396         }  
397         ViewRoot viewRoot = (ViewRoot) getRootView().getParent();  
398         if (viewRoot != null) {  
399             mTranslator = viewRoot.mTranslator;  
400         }  
401   
402         Resources res = getContext().getResources();  
403         if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) {  
404             mSurface.setCompatibleDisplayMetrics(res.getDisplayMetrics(), mTranslator);  
405         }  
406           
407         int myWidth = mRequestedWidth;  
408         if (myWidth <= 0) myWidth = getWidth();  
409         int myHeight = mRequestedHeight;  
410         if (myHeight <= 0) myHeight = getHeight();  
411   
412         getLocationInWindow(mLocation);  
413         final boolean creating = mWindow == null;  
414         final boolean formatChanged = mFormat != mRequestedFormat;  
415         final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;  
416         final boolean visibleChanged = mVisible != mRequestedVisible  
417                 || mNewSurfaceNeeded;  
418         final boolean typeChanged = mType != mRequestedType;  
419         if (force || creating || formatChanged || sizeChanged || visibleChanged  
420             || typeChanged || mLeft != mLocation[0] || mTop != mLocation[1]  
421             || mUpdateWindowNeeded || mReportDrawNeeded) {  
422   
423             if (localLOGV) Log.i(TAG, "Changes: creating=" + creating  
424                     + " format=" + formatChanged + " size=" + sizeChanged  
425                     + " visible=" + visibleChanged  
426                     + " left=" + (mLeft != mLocation[0])  
427                     + " top=" + (mTop != mLocation[1]));  
428   
429             try {  
430                 final boolean visible = mVisible = mRequestedVisible;  
431                 mLeft = mLocation[0];  
432                 mTop = mLocation[1];  
433                 mWidth = myWidth;  
434                 mHeight = myHeight;  
435                 mFormat = mRequestedFormat;  
436                 mType = mRequestedType;  
437   
438                 // Scaling/Translate window's layout here because mLayout is not used elsewhere.  
439                   
440                 // Places the window relative  
441                 mLayout.x = mLeft;  
442                 mLayout.y = mTop;  
443                 mLayout.width = getWidth();  
444                 mLayout.height = getHeight();  
445                 if (mTranslator != null) {  
446                     mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);  
447                 }  
448                   
449                 mLayout.format = mRequestedFormat;  
450                 mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE  
451                               | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
452                               | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS  
453                               | WindowManager.LayoutParams.FLAG_SCALED  
454                               | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
455                               | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE  
456                               ;  
457                 if (!getContext().getResources().getCompatibilityInfo().supportsScreen()) {  
458                     mLayout.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;  
459                 }  
460   
461                 mLayout.memoryType = mRequestedType;  
462   
463                 if (mWindow == null) {  
464                     mWindow = new MyWindow(this);  
465                     mLayout.type = mWindowType;  
466                     mLayout.gravity = Gravity.LEFT|Gravity.TOP;  
467                     mSession.add(mWindow, mLayout,  
468                             mVisible ? VISIBLE : GONE, mContentInsets);  
469                 }  
470                   
471                 if (visibleChanged && (!visible || mNewSurfaceNeeded)) {  
472                     reportSurfaceDestroyed();  
473                 }  
474   
475                 mNewSurfaceNeeded = false;  
476                   
477                 boolean realSizeChanged;  
478                 boolean reportDrawNeeded;  
479                   
480                 mSurfaceLock.lock();  
481                 try {  
482                     mUpdateWindowNeeded = false;  
483                     reportDrawNeeded = mReportDrawNeeded;  
484                     mReportDrawNeeded = false;  
485                     mDrawingStopped = !visible;  
486       
487                     final int relayoutResult = mSession.relayout(  
488                         mWindow, mLayout, mWidth, mHeight,  
489                             visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,  
490                             mVisibleInsets, mConfiguration, mSurface);  
491                     if ((relayoutResult&WindowManagerImpl.RELAYOUT_FIRST_TIME) != 0) {  
492                         mReportDrawNeeded = true;  
493                     }  
494                       
495                     if (localLOGV) Log.i(TAG, "New surface: " + mSurface  
496                             + ", vis=" + visible + ", frame=" + mWinFrame);  
497                       
498                     mSurfaceFrame.left = 0;  
499                     mSurfaceFrame.top = 0;  
500                     if (mTranslator == null) {  
501                         mSurfaceFrame.right = mWinFrame.width();  
502                         mSurfaceFrame.bottom = mWinFrame.height();  
503                     } else {  
504                         float appInvertedScale = mTranslator.applicationInvertedScale;  
505                         mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);  
506                         mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);  
507                     }  
508                       
509                     final int surfaceWidth = mSurfaceFrame.right;  
510                     final int surfaceHeight = mSurfaceFrame.bottom;  
511                     realSizeChanged = mLastSurfaceWidth != surfaceWidth  
512                             || mLastSurfaceHeight != surfaceHeight;  
513                     mLastSurfaceWidth = surfaceWidth;  
514                     mLastSurfaceHeight = surfaceHeight;  
515                 } finally {  
516                     mSurfaceLock.unlock();  
517                 }  
518   
519                 try {  
520                     if (visible) {  
521                         mDestroyReportNeeded = true;  
522   
523                         SurfaceHolder.Callback callbacks[];  
524                         synchronized (mCallbacks) {  
525                             callbacks = new SurfaceHolder.Callback[mCallbacks.size()];  
526                             mCallbacks.toArray(callbacks);  
527                         }  
528   
529                         if (visibleChanged) {  
530                             mIsCreating = true;  
531                             for (SurfaceHolder.Callback c : callbacks) {  
532                                 c.surfaceCreated(mSurfaceHolder);  
533                             }  
534                         }  
535                         if (creating || formatChanged || sizeChanged  
536                                 || visibleChanged || realSizeChanged) {  
537                             for (SurfaceHolder.Callback c : callbacks) {  
538                                 c.surfaceChanged(mSurfaceHolder, mFormat, myWidth, myHeight);  
539                             }  
540                         }  
541                     } else {  
542                         mSurface.release();  
543                     }  
544                 } finally {  
545                     mIsCreating = false;  
546                     if (creating || reportDrawNeeded) {  
547                         mSession.finishDrawing(mWindow);  
548                     }  
549                 }  
550             } catch (RemoteException ex) {  
551             }  
552             if (localLOGV) Log.v(  
553                 TAG, "Layout: x=" + mLayout.x + " y=" + mLayout.y +  
554                 " w=" + mLayout.width + " h=" + mLayout.height +  
555                 ", frame=" + mSurfaceFrame);  
556         }  
557     }  
558   
559     private void reportSurfaceDestroyed() {  
560         if (mDestroyReportNeeded) {  
561             mDestroyReportNeeded = false;  
562             SurfaceHolder.Callback callbacks[];  
563             synchronized (mCallbacks) {  
564                 callbacks = new SurfaceHolder.Callback[mCallbacks.size()];  
565                 mCallbacks.toArray(callbacks);  
566             }              
567             for (SurfaceHolder.Callback c : callbacks) {  
568                 c.surfaceDestroyed(mSurfaceHolder);  
569             }  
570         }  
571         super.onDetachedFromWindow();  
572     }  
573   
574     void handleGetNewSurface() {  
575         mNewSurfaceNeeded = true;  
576         updateWindow(false);  
577     }  
578   
579     /** 
580      * Check to see if the surface has fixed size dimensions or if the surface's 
581      * dimensions are dimensions are dependent on its current layout. 
582      * 
583      * @return true if the surface has dimensions that are fixed in size 
584      * @hide 
585      */  
586     public boolean isFixedSize() {  
587         return (mRequestedWidth != -1 || mRequestedHeight != -1);  
588     }  
589   
590     private static class MyWindow extends BaseIWindow {  
591         private final WeakReference<SurfaceView> mSurfaceView;  
592   
593         public MyWindow(SurfaceView surfaceView) {  
594             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);  
595         }  
596   
597         public void resized(int w, int h, Rect coveredInsets,  
598                 Rect visibleInsets, boolean reportDraw, Configuration newConfig) {  
599             SurfaceView surfaceView = mSurfaceView.get();  
600             if (surfaceView != null) {  
601                 if (localLOGV) Log.v(  
602                         "SurfaceView", surfaceView + " got resized: w=" +  
603                                 w + " h=" + h + ", cur w=" + mCurWidth + " h=" + mCurHeight);  
604                 surfaceView.mSurfaceLock.lock();  
605                 try {  
606                     if (reportDraw) {  
607                         surfaceView.mUpdateWindowNeeded = true;  
608                         surfaceView.mReportDrawNeeded = true;  
609                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);  
610                     } else if (surfaceView.mWinFrame.width() != w  
611                             || surfaceView.mWinFrame.height() != h) {  
612                         surfaceView.mUpdateWindowNeeded = true;  
613                         surfaceView.mHandler.sendEmptyMessage(UPDATE_WINDOW_MSG);  
614                     }  
615                 } finally {  
616                     surfaceView.mSurfaceLock.unlock();  
617                 }  
618             }  
619         }  
620   
621         public void dispatchKey(KeyEvent event) {  
622             SurfaceView surfaceView = mSurfaceView.get();  
623             if (surfaceView != null) {  
624                 //Log.w("SurfaceView", "Unexpected key event in surface: " + event);  
625                 if (surfaceView.mSession != null && surfaceView.mSurface != null) {  
626                     try {  
627                         surfaceView.mSession.finishKey(surfaceView.mWindow);  
628                     } catch (RemoteException ex) {  
629                     }  
630                 }  
631             }  
632         }  
633   
634         public void dispatchPointer(MotionEvent event, long eventTime,  
635                 boolean callWhenDone) {  
636             Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);  
637             //if (mSession != null && mSurface != null) {  
638             //    try {  
639             //        //mSession.finishKey(mWindow);  
640             //    } catch (RemoteException ex) {  
641             //    }  
642             //}  
643         }  
644   
645         public void dispatchTrackball(MotionEvent event, long eventTime,  
646                 boolean callWhenDone) {  
647             Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);  
648             //if (mSession != null && mSurface != null) {  
649             //    try {  
650             //        //mSession.finishKey(mWindow);  
651             //    } catch (RemoteException ex) {  
652             //    }  
653             //}  
654         }  
655   
656         public void dispatchAppVisibility(boolean visible) {  
657             // The point of SurfaceView is to let the app control the surface.  
658         }  
659   
660         public void dispatchGetNewSurface() {  
661             SurfaceView surfaceView = mSurfaceView.get();  
662             if (surfaceView != null) {  
663                 Message msg = surfaceView.mHandler.obtainMessage(GET_NEW_SURFACE_MSG);  
664                 surfaceView.mHandler.sendMessage(msg);  
665             }  
666         }  
667   
668         public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {  
669             Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);  
670         }  
671   
672         public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {  
673         }  
674   
675         int mCurWidth = -1;  
676         int mCurHeight = -1;  
677     }  
678   
679     private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {  
680           
681         private static final String LOG_TAG = "SurfaceHolder";  
682         private int mSaveCount;  
683           
684         public boolean isCreating() {  
685             return mIsCreating;  
686         }  
687   
688         public void addCallback(Callback callback) {  
689             synchronized (mCallbacks) {  
690                 // This is a linear search, but in practice we'll   
691                 // have only a couple callbacks, so it doesn't matter.  
692                 if (mCallbacks.contains(callback) == false) {        
693                     mCallbacks.add(callback);  
694                 }  
695             }  
696         }  
697   
698         public void removeCallback(Callback callback) {  
699             synchronized (mCallbacks) {  
700                 mCallbacks.remove(callback);  
701             }  
702         }  
703           
704         public void setFixedSize(int width, int height) {  
705             if (mRequestedWidth != width || mRequestedHeight != height) {  
706                 mRequestedWidth = width;  
707                 mRequestedHeight = height;  
708                 requestLayout();  
709             }  
710         }  
711   
712         public void setSizeFromLayout() {  
713             if (mRequestedWidth != -1 || mRequestedHeight != -1) {  
714                 mRequestedWidth = mRequestedHeight = -1;  
715                 requestLayout();  
716             }  
717         }  
718   
719         public void setFormat(int format) {  
720             mRequestedFormat = format;  
721             if (mWindow != null) {  
722                 updateWindow(false);  
723             }  
724         }  
725   
726         public void setType(int type) {  
727             switch (type) {  
728             case SURFACE_TYPE_HARDWARE:  
729             case SURFACE_TYPE_GPU:  
730                 // these are deprecated, treat as "NORMAL"  
731                 type = SURFACE_TYPE_NORMAL;  
732                 break;  
733             }  
734             switch (type) {  
735             case SURFACE_TYPE_NORMAL:  
736             case SURFACE_TYPE_PUSH_BUFFERS:  
737                 mRequestedType = type;  
738                 if (mWindow != null) {  
739                     updateWindow(false);  
740                 }  
741                 break;  
742             }  
743         }  
744   
745         public void setKeepScreenOn(boolean screenOn) {  
746             Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);  
747             msg.arg1 = screenOn ? 1 : 0;  
748             mHandler.sendMessage(msg);  
749         }  
750           
751         public Canvas lockCanvas() {  
752             return internalLockCanvas(null);  
753         }  
754   
755         public Canvas lockCanvas(Rect dirty) {  
756             return internalLockCanvas(dirty);  
757         }  
758   
759         private final Canvas internalLockCanvas(Rect dirty) {  
760             if (mType == SURFACE_TYPE_PUSH_BUFFERS) {  
761                 throw new BadSurfaceTypeException(  
762                         "Surface type is SURFACE_TYPE_PUSH_BUFFERS");  
763             }  
764             mSurfaceLock.lock();  
765   
766             if (localLOGV) Log.i(TAG, "Locking canvas... stopped="  
767                     + mDrawingStopped + ", win=" + mWindow);  
768   
769             Canvas c = null;  
770             if (!mDrawingStopped && mWindow != null) {  
771                 Rect frame = dirty != null ? dirty : mSurfaceFrame;  
772                 try {  
773                     c = mSurface.lockCanvas(frame);  
774                 } catch (Exception e) {  
775                     Log.e(LOG_TAG, "Exception locking surface", e);  
776                 }  
777             }  
778   
779             if (localLOGV) Log.i(TAG, "Returned canvas: " + c);  
780             if (c != null) {  
781                 mLastLockTime = SystemClock.uptimeMillis();  
782                 return c;  
783             }  
784               
785             // If the Surface is not ready to be drawn, then return null,  
786             // but throttle calls to this function so it isn't called more  
787             // than every 100ms.  
788             long now = SystemClock.uptimeMillis();  
789             long nextTime = mLastLockTime + 100;  
790             if (nextTime > now) {  
791                 try {  
792                     Thread.sleep(nextTime-now);  
793                 } catch (InterruptedException e) {  
794                 }  
795                 now = SystemClock.uptimeMillis();  
796             }  
797             mLastLockTime = now;  
798             mSurfaceLock.unlock();  
799               
800             return null;  
801         }  
802   
803         public void unlockCanvasAndPost(Canvas canvas) {  
804             mSurface.unlockCanvasAndPost(canvas);  
805             mSurfaceLock.unlock();  
806         }  
807   
808         public Surface getSurface() {  
809             return mSurface;  
810         }  
811   
812         public Rect getSurfaceFrame() {  
813             return mSurfaceFrame;  
814         }  
815     };  
816 }

 

posted @ 2015-06-10 19:58  f9q  阅读(384)  评论(0)    收藏  举报