BaseSurfaceHolder.java revision 4c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3
1package com.android.internal.view; 2 3import android.graphics.Canvas; 4import android.graphics.PixelFormat; 5import android.graphics.Rect; 6import android.os.SystemClock; 7import android.util.Log; 8import android.view.Surface; 9import android.view.SurfaceHolder; 10 11import java.util.ArrayList; 12import java.util.concurrent.locks.ReentrantLock; 13 14public abstract class BaseSurfaceHolder implements SurfaceHolder { 15 private static final String TAG = "BaseSurfaceHolder"; 16 static final boolean DEBUG = false; 17 18 public final ArrayList<SurfaceHolder.Callback> mCallbacks 19 = new ArrayList<SurfaceHolder.Callback>(); 20 21 public final ReentrantLock mSurfaceLock = new ReentrantLock(); 22 public final Surface mSurface = new Surface(); 23 24 int mRequestedWidth = -1; 25 int mRequestedHeight = -1; 26 int mRequestedFormat = PixelFormat.OPAQUE; 27 int mRequestedType = -1; 28 29 long mLastLockTime = 0; 30 31 int mType = -1; 32 final Rect mSurfaceFrame = new Rect(); 33 34 public abstract void onUpdateSurface(); 35 public abstract void onRelayoutContainer(); 36 public abstract boolean onAllowLockCanvas(); 37 38 public int getRequestedWidth() { 39 return mRequestedWidth; 40 } 41 42 public int getRequestedHeight() { 43 return mRequestedHeight; 44 } 45 46 public int getRequestedFormat() { 47 return mRequestedFormat; 48 } 49 50 public int getRequestedType() { 51 return mRequestedType; 52 } 53 54 public void addCallback(Callback callback) { 55 synchronized (mCallbacks) { 56 // This is a linear search, but in practice we'll 57 // have only a couple callbacks, so it doesn't matter. 58 if (mCallbacks.contains(callback) == false) { 59 mCallbacks.add(callback); 60 } 61 } 62 } 63 64 public void removeCallback(Callback callback) { 65 synchronized (mCallbacks) { 66 mCallbacks.remove(callback); 67 } 68 } 69 70 public void setFixedSize(int width, int height) { 71 if (mRequestedWidth != width || mRequestedHeight != height) { 72 mRequestedWidth = width; 73 mRequestedHeight = height; 74 onRelayoutContainer(); 75 } 76 } 77 78 public void setSizeFromLayout() { 79 if (mRequestedWidth != -1 || mRequestedHeight != -1) { 80 mRequestedWidth = mRequestedHeight = -1; 81 onRelayoutContainer(); 82 } 83 } 84 85 public void setFormat(int format) { 86 if (mRequestedFormat != format) { 87 mRequestedFormat = format; 88 onUpdateSurface(); 89 } 90 } 91 92 public void setType(int type) { 93 switch (type) { 94 case SURFACE_TYPE_NORMAL: 95 case SURFACE_TYPE_HARDWARE: 96 case SURFACE_TYPE_GPU: 97 case SURFACE_TYPE_PUSH_BUFFERS: 98 if (mRequestedType != type) { 99 mRequestedType = type; 100 onUpdateSurface(); 101 } 102 break; 103 } 104 } 105 106 public Canvas lockCanvas() { 107 return internalLockCanvas(null); 108 } 109 110 public Canvas lockCanvas(Rect dirty) { 111 return internalLockCanvas(dirty); 112 } 113 114 private final Canvas internalLockCanvas(Rect dirty) { 115 if (mType == SURFACE_TYPE_PUSH_BUFFERS) { 116 throw new BadSurfaceTypeException( 117 "Surface type is SURFACE_TYPE_PUSH_BUFFERS"); 118 } 119 mSurfaceLock.lock(); 120 121 if (DEBUG) Log.i(TAG, "Locking canvas..,"); 122 123 Canvas c = null; 124 if (onAllowLockCanvas()) { 125 Rect frame = dirty != null ? dirty : mSurfaceFrame; 126 try { 127 c = mSurface.lockCanvas(frame); 128 } catch (Exception e) { 129 Log.e(TAG, "Exception locking surface", e); 130 } 131 } 132 133 if (DEBUG) Log.i(TAG, "Returned canvas: " + c); 134 if (c != null) { 135 mLastLockTime = SystemClock.uptimeMillis(); 136 return c; 137 } 138 139 // If the Surface is not ready to be drawn, then return null, 140 // but throttle calls to this function so it isn't called more 141 // than every 100ms. 142 long now = SystemClock.uptimeMillis(); 143 long nextTime = mLastLockTime + 100; 144 if (nextTime > now) { 145 try { 146 Thread.sleep(nextTime-now); 147 } catch (InterruptedException e) { 148 } 149 now = SystemClock.uptimeMillis(); 150 } 151 mLastLockTime = now; 152 mSurfaceLock.unlock(); 153 154 return null; 155 } 156 157 public void unlockCanvasAndPost(Canvas canvas) { 158 mSurface.unlockCanvasAndPost(canvas); 159 mSurfaceLock.unlock(); 160 } 161 162 public Surface getSurface() { 163 return mSurface; 164 } 165 166 public Rect getSurfaceFrame() { 167 return mSurfaceFrame; 168 } 169}; 170