• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 com.android.internal.view;
18 
19 import android.graphics.Canvas;
20 import android.graphics.PixelFormat;
21 import android.graphics.Rect;
22 import android.os.SystemClock;
23 import android.util.Log;
24 import android.view.Surface;
25 import android.view.SurfaceHolder;
26 
27 import java.util.ArrayList;
28 import java.util.concurrent.locks.ReentrantLock;
29 
30 public abstract class BaseSurfaceHolder implements SurfaceHolder {
31     private static final String TAG = "BaseSurfaceHolder";
32     static final boolean DEBUG = false;
33 
34     public final ArrayList<SurfaceHolder.Callback> mCallbacks
35             = new ArrayList<SurfaceHolder.Callback>();
36     SurfaceHolder.Callback[] mGottenCallbacks;
37     boolean mHaveGottenCallbacks;
38 
39     public final ReentrantLock mSurfaceLock = new ReentrantLock();
40     public Surface mSurface = new Surface();
41 
42     int mRequestedWidth = -1;
43     int mRequestedHeight = -1;
44     /** @hide */
45     protected int mRequestedFormat = PixelFormat.OPAQUE;
46     int mRequestedType = -1;
47 
48     long mLastLockTime = 0;
49 
50     int mType = -1;
51     final Rect mSurfaceFrame = new Rect();
52 
onUpdateSurface()53     public abstract void onUpdateSurface();
onRelayoutContainer()54     public abstract void onRelayoutContainer();
onAllowLockCanvas()55     public abstract boolean onAllowLockCanvas();
56 
getRequestedWidth()57     public int getRequestedWidth() {
58         return mRequestedWidth;
59     }
60 
getRequestedHeight()61     public int getRequestedHeight() {
62         return mRequestedHeight;
63     }
64 
getRequestedFormat()65     public int getRequestedFormat() {
66         return mRequestedFormat;
67     }
68 
getRequestedType()69     public int getRequestedType() {
70         return mRequestedType;
71     }
72 
addCallback(Callback callback)73     public void addCallback(Callback callback) {
74         synchronized (mCallbacks) {
75             // This is a linear search, but in practice we'll
76             // have only a couple callbacks, so it doesn't matter.
77             if (mCallbacks.contains(callback) == false) {
78                 mCallbacks.add(callback);
79             }
80         }
81     }
82 
removeCallback(Callback callback)83     public void removeCallback(Callback callback) {
84         synchronized (mCallbacks) {
85             mCallbacks.remove(callback);
86         }
87     }
88 
getCallbacks()89     public SurfaceHolder.Callback[] getCallbacks() {
90         if (mHaveGottenCallbacks) {
91             return mGottenCallbacks;
92         }
93 
94         synchronized (mCallbacks) {
95             final int N = mCallbacks.size();
96             if (N > 0) {
97                 if (mGottenCallbacks == null || mGottenCallbacks.length != N) {
98                     mGottenCallbacks = new SurfaceHolder.Callback[N];
99                 }
100                 mCallbacks.toArray(mGottenCallbacks);
101             } else {
102                 mGottenCallbacks = null;
103             }
104             mHaveGottenCallbacks = true;
105         }
106 
107         return mGottenCallbacks;
108     }
109 
ungetCallbacks()110     public void ungetCallbacks() {
111         mHaveGottenCallbacks = false;
112     }
113 
setFixedSize(int width, int height)114     public void setFixedSize(int width, int height) {
115         if (mRequestedWidth != width || mRequestedHeight != height) {
116             mRequestedWidth = width;
117             mRequestedHeight = height;
118             onRelayoutContainer();
119         }
120     }
121 
setSizeFromLayout()122     public void setSizeFromLayout() {
123         if (mRequestedWidth != -1 || mRequestedHeight != -1) {
124             mRequestedWidth = mRequestedHeight = -1;
125             onRelayoutContainer();
126         }
127     }
128 
setFormat(int format)129     public void setFormat(int format) {
130         if (mRequestedFormat != format) {
131             mRequestedFormat = format;
132             onUpdateSurface();
133         }
134     }
135 
setType(int type)136     public void setType(int type) {
137         switch (type) {
138         case SURFACE_TYPE_HARDWARE:
139         case SURFACE_TYPE_GPU:
140             // these are deprecated, treat as "NORMAL"
141             type = SURFACE_TYPE_NORMAL;
142             break;
143         }
144         switch (type) {
145         case SURFACE_TYPE_NORMAL:
146         case SURFACE_TYPE_PUSH_BUFFERS:
147             if (mRequestedType != type) {
148                 mRequestedType = type;
149                 onUpdateSurface();
150             }
151             break;
152         }
153     }
154 
lockCanvas()155     public Canvas lockCanvas() {
156         return internalLockCanvas(null);
157     }
158 
lockCanvas(Rect dirty)159     public Canvas lockCanvas(Rect dirty) {
160         return internalLockCanvas(dirty);
161     }
162 
internalLockCanvas(Rect dirty)163     private final Canvas internalLockCanvas(Rect dirty) {
164         if (mType == SURFACE_TYPE_PUSH_BUFFERS) {
165             throw new BadSurfaceTypeException(
166                     "Surface type is SURFACE_TYPE_PUSH_BUFFERS");
167         }
168         mSurfaceLock.lock();
169 
170         if (DEBUG) Log.i(TAG, "Locking canvas..,");
171 
172         Canvas c = null;
173         if (onAllowLockCanvas()) {
174             Rect frame = dirty != null ? dirty : mSurfaceFrame;
175             try {
176                 c = mSurface.lockCanvas(frame);
177             } catch (Exception e) {
178                 Log.e(TAG, "Exception locking surface", e);
179             }
180         }
181 
182         if (DEBUG) Log.i(TAG, "Returned canvas: " + c);
183         if (c != null) {
184             mLastLockTime = SystemClock.uptimeMillis();
185             return c;
186         }
187 
188         // If the Surface is not ready to be drawn, then return null,
189         // but throttle calls to this function so it isn't called more
190         // than every 100ms.
191         long now = SystemClock.uptimeMillis();
192         long nextTime = mLastLockTime + 100;
193         if (nextTime > now) {
194             try {
195                 Thread.sleep(nextTime-now);
196             } catch (InterruptedException e) {
197             }
198             now = SystemClock.uptimeMillis();
199         }
200         mLastLockTime = now;
201         mSurfaceLock.unlock();
202 
203         return null;
204     }
205 
unlockCanvasAndPost(Canvas canvas)206     public void unlockCanvasAndPost(Canvas canvas) {
207         mSurface.unlockCanvasAndPost(canvas);
208         mSurfaceLock.unlock();
209     }
210 
getSurface()211     public Surface getSurface() {
212         return mSurface;
213     }
214 
getSurfaceFrame()215     public Rect getSurfaceFrame() {
216         return mSurfaceFrame;
217     }
218 };
219