• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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