1 package com.android.internal.view; 2 3 import android.graphics.Canvas; 4 import android.graphics.PixelFormat; 5 import android.graphics.Rect; 6 import android.os.SystemClock; 7 import android.util.Log; 8 import android.view.Surface; 9 import android.view.SurfaceHolder; 10 11 import java.util.ArrayList; 12 import java.util.concurrent.locks.ReentrantLock; 13 14 public 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 onUpdateSurface()34 public abstract void onUpdateSurface(); onRelayoutContainer()35 public abstract void onRelayoutContainer(); onAllowLockCanvas()36 public abstract boolean onAllowLockCanvas(); 37 getRequestedWidth()38 public int getRequestedWidth() { 39 return mRequestedWidth; 40 } 41 getRequestedHeight()42 public int getRequestedHeight() { 43 return mRequestedHeight; 44 } 45 getRequestedFormat()46 public int getRequestedFormat() { 47 return mRequestedFormat; 48 } 49 getRequestedType()50 public int getRequestedType() { 51 return mRequestedType; 52 } 53 addCallback(Callback callback)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 removeCallback(Callback callback)64 public void removeCallback(Callback callback) { 65 synchronized (mCallbacks) { 66 mCallbacks.remove(callback); 67 } 68 } 69 setFixedSize(int width, int height)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 setSizeFromLayout()78 public void setSizeFromLayout() { 79 if (mRequestedWidth != -1 || mRequestedHeight != -1) { 80 mRequestedWidth = mRequestedHeight = -1; 81 onRelayoutContainer(); 82 } 83 } 84 setFormat(int format)85 public void setFormat(int format) { 86 if (mRequestedFormat != format) { 87 mRequestedFormat = format; 88 onUpdateSurface(); 89 } 90 } 91 setType(int type)92 public void setType(int type) { 93 switch (type) { 94 case SURFACE_TYPE_HARDWARE: 95 case SURFACE_TYPE_GPU: 96 // these are deprecated, treat as "NORMAL" 97 type = SURFACE_TYPE_NORMAL; 98 break; 99 } 100 switch (type) { 101 case SURFACE_TYPE_NORMAL: 102 case SURFACE_TYPE_PUSH_BUFFERS: 103 if (mRequestedType != type) { 104 mRequestedType = type; 105 onUpdateSurface(); 106 } 107 break; 108 } 109 } 110 lockCanvas()111 public Canvas lockCanvas() { 112 return internalLockCanvas(null); 113 } 114 lockCanvas(Rect dirty)115 public Canvas lockCanvas(Rect dirty) { 116 return internalLockCanvas(dirty); 117 } 118 internalLockCanvas(Rect dirty)119 private final Canvas internalLockCanvas(Rect dirty) { 120 if (mType == SURFACE_TYPE_PUSH_BUFFERS) { 121 throw new BadSurfaceTypeException( 122 "Surface type is SURFACE_TYPE_PUSH_BUFFERS"); 123 } 124 mSurfaceLock.lock(); 125 126 if (DEBUG) Log.i(TAG, "Locking canvas..,"); 127 128 Canvas c = null; 129 if (onAllowLockCanvas()) { 130 Rect frame = dirty != null ? dirty : mSurfaceFrame; 131 try { 132 c = mSurface.lockCanvas(frame); 133 } catch (Exception e) { 134 Log.e(TAG, "Exception locking surface", e); 135 } 136 } 137 138 if (DEBUG) Log.i(TAG, "Returned canvas: " + c); 139 if (c != null) { 140 mLastLockTime = SystemClock.uptimeMillis(); 141 return c; 142 } 143 144 // If the Surface is not ready to be drawn, then return null, 145 // but throttle calls to this function so it isn't called more 146 // than every 100ms. 147 long now = SystemClock.uptimeMillis(); 148 long nextTime = mLastLockTime + 100; 149 if (nextTime > now) { 150 try { 151 Thread.sleep(nextTime-now); 152 } catch (InterruptedException e) { 153 } 154 now = SystemClock.uptimeMillis(); 155 } 156 mLastLockTime = now; 157 mSurfaceLock.unlock(); 158 159 return null; 160 } 161 unlockCanvasAndPost(Canvas canvas)162 public void unlockCanvasAndPost(Canvas canvas) { 163 mSurface.unlockCanvasAndPost(canvas); 164 mSurfaceLock.unlock(); 165 } 166 getSurface()167 public Surface getSurface() { 168 return mSurface; 169 } 170 getSurfaceFrame()171 public Rect getSurfaceFrame() { 172 return mSurfaceFrame; 173 } 174 }; 175