BaseSurfaceHolder.java revision 317a6280cc109e873646e4652be1582d870eedfd
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_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
111    public Canvas lockCanvas() {
112        return internalLockCanvas(null);
113    }
114
115    public Canvas lockCanvas(Rect dirty) {
116        return internalLockCanvas(dirty);
117    }
118
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
162    public void unlockCanvasAndPost(Canvas canvas) {
163        mSurface.unlockCanvasAndPost(canvas);
164        mSurfaceLock.unlock();
165    }
166
167    public Surface getSurface() {
168        return mSurface;
169    }
170
171    public Rect getSurfaceFrame() {
172        return mSurfaceFrame;
173    }
174};
175