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