The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2007 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 android.view; |
| 18 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 19 | import dalvik.system.CloseGuard; |
| 20 | |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 21 | import android.content.res.CompatibilityInfo.Translator; |
Jeff Brown | 0b722fe | 2012-08-24 22:40:14 -0700 | [diff] [blame] | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.Matrix; |
| 25 | import android.graphics.Rect; |
| 26 | import android.graphics.Region; |
| 27 | import android.graphics.SurfaceTexture; |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 28 | import android.os.IBinder; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 29 | import android.os.Parcelable; |
| 30 | import android.os.Parcel; |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 31 | import android.os.SystemProperties; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 32 | import android.util.Log; |
| 33 | |
| 34 | /** |
Glenn Kasten | 334031c | 2010-11-09 21:54:38 -0800 | [diff] [blame] | 35 | * Handle onto a raw buffer that is being managed by the screen compositor. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 36 | */ |
| 37 | public class Surface implements Parcelable { |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 38 | private static final String TAG = "Surface"; |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 39 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 40 | private static final boolean HEADLESS = "1".equals( |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 41 | SystemProperties.get("ro.config.headless", "0")); |
| 42 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 43 | public static final Parcelable.Creator<Surface> CREATOR = |
| 44 | new Parcelable.Creator<Surface>() { |
| 45 | public Surface createFromParcel(Parcel source) { |
| 46 | try { |
| 47 | Surface s = new Surface(); |
| 48 | s.readFromParcel(source); |
| 49 | return s; |
| 50 | } catch (Exception e) { |
| 51 | Log.e(TAG, "Exception creating surface from parcel", e); |
| 52 | return null; |
| 53 | } |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 54 | } |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 55 | |
| 56 | public Surface[] newArray(int size) { |
| 57 | return new Surface[size]; |
| 58 | } |
| 59 | }; |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 60 | |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 61 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 62 | * Rotation constant: 0 degree rotation (natural orientation) |
Jamie Gennis | df0c84f | 2011-08-28 15:09:17 -0700 | [diff] [blame] | 63 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 64 | public static final int ROTATION_0 = 0; |
Jamie Gennis | df0c84f | 2011-08-28 15:09:17 -0700 | [diff] [blame] | 65 | |
| 66 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 67 | * Rotation constant: 90 degree rotation. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 68 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 69 | public static final int ROTATION_90 = 1; |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 70 | |
| 71 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 72 | * Rotation constant: 180 degree rotation. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 73 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 74 | public static final int ROTATION_180 = 2; |
| 75 | |
| 76 | /** |
| 77 | * Rotation constant: 270 degree rotation. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 78 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 79 | public static final int ROTATION_270 = 3; |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 80 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 81 | /* built-in physical display ids (keep in sync with ISurfaceComposer.h) |
| 82 | * these are different from the logical display ids used elsewhere in the framework */ |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 83 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 84 | /** |
| 85 | * Built-in physical display id: Main display. |
| 86 | * Use only with {@link #getBuiltInDisplay()}. |
| 87 | * @hide |
| 88 | */ |
| 89 | public static final int BUILT_IN_DISPLAY_ID_MAIN = 0; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 90 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 91 | /** |
| 92 | * Built-in physical display id: Attached HDMI display. |
| 93 | * Use only with {@link #getBuiltInDisplay()}. |
| 94 | * @hide |
| 95 | */ |
| 96 | public static final int BUILT_IN_DISPLAY_ID_HDMI = 1; |
| 97 | |
| 98 | /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */ |
| 99 | |
| 100 | /** |
| 101 | * Surface creation flag: Surface is created hidden |
| 102 | * @hide */ |
| 103 | public static final int HIDDEN = 0x00000004; |
| 104 | |
| 105 | /** |
| 106 | * Surface creation flag: The surface contains secure content, special |
| 107 | * measures will be taken to disallow the surface's content to be copied |
| 108 | * from another process. In particular, screenshots and VNC servers will |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 109 | * be disabled, but other measures can take place, for instance the |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 110 | * surface might not be hardware accelerated. |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 111 | * @hide |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 112 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 113 | public static final int SECURE = 0x00000080; |
| 114 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 115 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 116 | * Surface creation flag: Creates a surface where color components are interpreted |
| 117 | * as "non pre-multiplied" by their alpha channel. Of course this flag is |
| 118 | * meaningless for surfaces without an alpha channel. By default |
| 119 | * surfaces are pre-multiplied, which means that each color component is |
| 120 | * already multiplied by its alpha value. In this case the blending |
| 121 | * equation used is: |
| 122 | * |
| 123 | * DEST = SRC + DEST * (1-SRC_ALPHA) |
| 124 | * |
| 125 | * By contrast, non pre-multiplied surfaces use the following equation: |
| 126 | * |
| 127 | * DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA) |
| 128 | * |
| 129 | * pre-multiplied surfaces must always be used if transparent pixels are |
| 130 | * composited on top of each-other into the surface. A pre-multiplied |
| 131 | * surface can never lower the value of the alpha component of a given |
| 132 | * pixel. |
| 133 | * |
| 134 | * In some rare situations, a non pre-multiplied surface is preferable. |
| 135 | * @hide |
| 136 | */ |
| 137 | public static final int NON_PREMULTIPLIED = 0x00000100; |
| 138 | |
| 139 | /** |
| 140 | * Surface creation flag: Indicates that the surface must be considered opaque, |
| 141 | * even if its pixel format is set to translucent. This can be useful if an |
Romain Guy | d10cd57 | 2010-10-10 13:33:22 -0700 | [diff] [blame] | 142 | * application needs full RGBA 8888 support for instance but will |
| 143 | * still draw every pixel opaque. |
Romain Guy | d10cd57 | 2010-10-10 13:33:22 -0700 | [diff] [blame] | 144 | * @hide |
| 145 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 146 | public static final int OPAQUE = 0x00000400; |
| 147 | |
Glenn Kasten | d6f5bde | 2011-01-19 15:27:27 -0800 | [diff] [blame] | 148 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 149 | * Surface creation flag: Application requires a hardware-protected path to an |
Glenn Kasten | d6f5bde | 2011-01-19 15:27:27 -0800 | [diff] [blame] | 150 | * external display sink. If a hardware-protected path is not available, |
| 151 | * then this surface will not be displayed on the external sink. |
Glenn Kasten | d6f5bde | 2011-01-19 15:27:27 -0800 | [diff] [blame] | 152 | * @hide |
| 153 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 154 | public static final int PROTECTED_APP = 0x00000800; |
Glenn Kasten | d6f5bde | 2011-01-19 15:27:27 -0800 | [diff] [blame] | 155 | |
| 156 | // 0x1000 is reserved for an independent DRM protected flag in framework |
| 157 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 158 | /** |
| 159 | * Surface creation flag: Creates a normal surface. |
| 160 | * This is the default. |
| 161 | * @hide |
| 162 | */ |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 163 | public static final int FX_SURFACE_NORMAL = 0x00000000; |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 164 | |
| 165 | /** |
| 166 | * Surface creation flag: Creates a Blur surface. |
| 167 | * Everything behind this surface is blurred by some amount. |
| 168 | * The quality and refresh speed of the blur effect is not settable or guaranteed. |
| 169 | * It is an error to lock a Blur surface, since it doesn't have a backing store. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 170 | * @hide |
Mathias Agopian | 67403e0 | 2011-08-22 17:47:06 -0700 | [diff] [blame] | 171 | * @deprecated |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 172 | */ |
Mathias Agopian | 67403e0 | 2011-08-22 17:47:06 -0700 | [diff] [blame] | 173 | @Deprecated |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 174 | public static final int FX_SURFACE_BLUR = 0x00010000; |
| 175 | |
| 176 | /** |
| 177 | * Surface creation flag: Creates a Dim surface. |
| 178 | * Everything behind this surface is dimmed by the amount specified |
| 179 | * in {@link #setAlpha}. It is an error to lock a Dim surface, since it |
| 180 | * doesn't have a backing store. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 181 | * @hide |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 182 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 183 | public static final int FX_SURFACE_DIM = 0x00020000; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 184 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 185 | /** |
| 186 | * @hide |
| 187 | */ |
| 188 | public static final int FX_SURFACE_SCREENSHOT = 0x00030000; |
Mathias Agopian | 0ab84ef | 2011-10-13 16:02:48 -0700 | [diff] [blame] | 189 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 190 | /** |
| 191 | * Mask used for FX values above. |
| 192 | * @hide |
| 193 | */ |
| 194 | public static final int FX_SURFACE_MASK = 0x000F0000; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 195 | |
| 196 | /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */ |
| 197 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 198 | /** |
| 199 | * Surface flag: Hide the surface. |
| 200 | * Equivalent to calling hide(). |
| 201 | * @hide |
| 202 | */ |
| 203 | public static final int SURFACE_HIDDEN = 0x01; |
Mathias Agopian | c87c4a3 | 2009-07-28 15:59:52 -0700 | [diff] [blame] | 204 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 205 | |
| 206 | private final CloseGuard mCloseGuard = CloseGuard.get(); |
| 207 | private String mName; |
| 208 | |
| 209 | // Note: These fields are accessed by native code. |
Ted Bonkenburg | 0de171b | 2011-07-15 15:10:10 -0700 | [diff] [blame] | 210 | // The mSurfaceControl will only be present for Surfaces used by the window |
| 211 | // server or system processes. When this class is parceled we defer to the |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 212 | // mSurfaceControl to do the parceling. Otherwise we parcel the |
| 213 | // mNativeSurface. |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 214 | private int mNativeSurface; // Surface* |
| 215 | private int mNativeSurfaceControl; // SurfaceControl* |
| 216 | private int mGenerationId; // incremented each time mNativeSurface changes |
| 217 | private final Canvas mCanvas = new CompatibleCanvas(); |
| 218 | private int mCanvasSaveCount; // Canvas save count at time of lockCanvas() |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 219 | |
Dianne Hackborn | 5be8de3 | 2011-05-24 18:11:57 -0700 | [diff] [blame] | 220 | // The Translator for density compatibility mode. This is used for scaling |
| 221 | // the canvas to perform the appropriate density transformation. |
| 222 | private Translator mCompatibilityTranslator; |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 223 | |
| 224 | // A matrix to scale the matrix set by application. This is set to null for |
| 225 | // non compatibility mode. |
| 226 | private Matrix mCompatibleMatrix; |
Mitsuru Oshima | 38ed7d77 | 2009-07-21 14:39:34 -0700 | [diff] [blame] | 227 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 228 | private native void nativeCreate(SurfaceSession session, String name, |
| 229 | int w, int h, int format, int flags) |
| 230 | throws OutOfResourcesException; |
| 231 | private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture) |
| 232 | throws OutOfResourcesException; |
| 233 | private native void nativeRelease(); |
| 234 | private native void nativeDestroy(); |
Mathias Agopian | f5e32f3 | 2010-03-23 16:44:27 -0700 | [diff] [blame] | 235 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 236 | private native boolean nativeIsValid(); |
| 237 | private native int nativeGetIdentity(); |
| 238 | private native boolean nativeIsConsumerRunningBehind(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 239 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 240 | private native Canvas nativeLockCanvas(Rect dirty); |
| 241 | private native void nativeUnlockCanvasAndPost(Canvas canvas); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 242 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 243 | private static native Bitmap nativeScreenshot(IBinder displayToken, |
| 244 | int width, int height, int minLayer, int maxLayer, boolean allLayers); |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 245 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 246 | private static native void nativeOpenTransaction(); |
| 247 | private static native void nativeCloseTransaction(); |
Jamie Gennis | b6ce6e4 | 2012-10-15 19:14:58 -0700 | [diff] [blame] | 248 | private static native void nativeSetAnimationTransaction(); |
Jeff Brown | 0b722fe | 2012-08-24 22:40:14 -0700 | [diff] [blame] | 249 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 250 | private native void nativeSetLayer(int zorder); |
| 251 | private native void nativeSetPosition(float x, float y); |
| 252 | private native void nativeSetSize(int w, int h); |
| 253 | private native void nativeSetTransparentRegionHint(Region region); |
| 254 | private native void nativeSetAlpha(float alpha); |
| 255 | private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy); |
| 256 | private native void nativeSetFlags(int flags, int mask); |
| 257 | private native void nativeSetWindowCrop(Rect crop); |
| 258 | private native void nativeSetLayerStack(int layerStack); |
Jeff Brown | 0b722fe | 2012-08-24 22:40:14 -0700 | [diff] [blame] | 259 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 260 | private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId); |
Jamie Gennis | 7bbf816 | 2012-10-19 18:29:29 -0700 | [diff] [blame] | 261 | private static native IBinder nativeCreateDisplay(String name, boolean secure); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 262 | private static native void nativeSetDisplaySurface( |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 263 | IBinder displayToken, Surface surface); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 264 | private static native void nativeSetDisplayLayerStack( |
| 265 | IBinder displayToken, int layerStack); |
Mathias Agopian | 63f1c43 | 2012-09-04 19:29:13 -0700 | [diff] [blame] | 266 | private static native void nativeSetDisplayProjection( |
| 267 | IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 268 | private static native boolean nativeGetDisplayInfo( |
| 269 | IBinder displayToken, PhysicalDisplayInfo outInfo); |
Jeff Brown | 9e316a1 | 2012-10-08 19:17:06 -0700 | [diff] [blame] | 270 | private static native void nativeBlankDisplay(IBinder displayToken); |
| 271 | private static native void nativeUnblankDisplay(IBinder displayToken); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 272 | |
| 273 | private native void nativeCopyFrom(Surface other); |
| 274 | private native void nativeTransferFrom(Surface other); |
| 275 | private native void nativeReadFromParcel(Parcel source); |
| 276 | private native void nativeWriteToParcel(Parcel dest); |
| 277 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 278 | |
| 279 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 280 | * Create an empty surface, which will later be filled in by readFromParcel(). |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 281 | * @hide |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 282 | */ |
| 283 | public Surface() { |
Kevin Hester | b85c933 | 2012-03-08 17:06:56 -0800 | [diff] [blame] | 284 | checkHeadless(); |
| 285 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 286 | mCloseGuard.open("release"); |
Mitsuru Oshima | 38ed7d77 | 2009-07-21 14:39:34 -0700 | [diff] [blame] | 287 | } |
| 288 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 289 | /** |
| 290 | * Create a surface with a name. |
| 291 | * |
| 292 | * The surface creation flags specify what kind of surface to create and |
| 293 | * certain options such as whether the surface can be assumed to be opaque |
| 294 | * and whether it should be initially hidden. Surfaces should always be |
| 295 | * created with the {@link #HIDDEN} flag set to ensure that they are not |
| 296 | * made visible prematurely before all of the surface's properties have been |
| 297 | * configured. |
| 298 | * |
| 299 | * Good practice is to first create the surface with the {@link #HIDDEN} flag |
| 300 | * specified, open a transaction, set the surface layer, layer stack, alpha, |
| 301 | * and position, call {@link #show} if appropriate, and close the transaction. |
| 302 | * |
| 303 | * @param session The surface session, must not be null. |
| 304 | * @param name The surface name, must not be null. |
| 305 | * @param w The surface initial width. |
| 306 | * @param h The surface initial height. |
| 307 | * @param flags The surface creation flags. Should always include {@link #HIDDEN} |
| 308 | * in the creation flags. |
| 309 | * @hide |
| 310 | */ |
| 311 | public Surface(SurfaceSession session, |
| 312 | String name, int w, int h, int format, int flags) |
| 313 | throws OutOfResourcesException { |
| 314 | if (session == null) { |
| 315 | throw new IllegalArgumentException("session must not be null"); |
| 316 | } |
| 317 | if (name == null) { |
| 318 | throw new IllegalArgumentException("name must not be null"); |
| 319 | } |
| 320 | |
| 321 | if ((flags & HIDDEN) == 0) { |
| 322 | Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set " |
| 323 | + "to ensure that they are not made visible prematurely before " |
| 324 | + "all of the surface's properties have been configured. " |
| 325 | + "Set the other properties and make the surface visible within " |
| 326 | + "a transaction. New surface name: " + name, |
| 327 | new Throwable()); |
| 328 | } |
| 329 | |
| 330 | checkHeadless(); |
| 331 | |
| 332 | mName = name; |
| 333 | nativeCreate(session, name, w, h, format, flags); |
| 334 | |
| 335 | mCloseGuard.open("release"); |
| 336 | } |
| 337 | |
| 338 | /** |
| 339 | * Create Surface from a {@link SurfaceTexture}. |
| 340 | * |
| 341 | * Images drawn to the Surface will be made available to the {@link |
| 342 | * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link |
| 343 | * SurfaceTexture#updateTexImage}. |
| 344 | * |
| 345 | * @param surfaceTexture The {@link SurfaceTexture} that is updated by this |
| 346 | * Surface. |
| 347 | */ |
| 348 | public Surface(SurfaceTexture surfaceTexture) { |
| 349 | if (surfaceTexture == null) { |
| 350 | throw new IllegalArgumentException("surfaceTexture must not be null"); |
| 351 | } |
| 352 | |
| 353 | checkHeadless(); |
| 354 | |
| 355 | mName = surfaceTexture.toString(); |
| 356 | try { |
| 357 | nativeCreateFromSurfaceTexture(surfaceTexture); |
| 358 | } catch (OutOfResourcesException ex) { |
| 359 | // We can't throw OutOfResourcesException because it would be an API change. |
| 360 | throw new RuntimeException(ex); |
| 361 | } |
| 362 | |
| 363 | mCloseGuard.open("release"); |
| 364 | } |
| 365 | |
| 366 | @Override |
| 367 | protected void finalize() throws Throwable { |
| 368 | try { |
| 369 | if (mCloseGuard != null) { |
| 370 | mCloseGuard.warnIfOpen(); |
| 371 | } |
| 372 | nativeRelease(); |
| 373 | } finally { |
| 374 | super.finalize(); |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | /** |
| 379 | * Release the local reference to the server-side surface. |
| 380 | * Always call release() when you're done with a Surface. |
| 381 | * This will make the surface invalid. |
| 382 | */ |
| 383 | public void release() { |
| 384 | nativeRelease(); |
| 385 | mCloseGuard.close(); |
| 386 | } |
| 387 | |
| 388 | /** |
| 389 | * Free all server-side state associated with this surface and |
| 390 | * release this object's reference. This method can only be |
| 391 | * called from the process that created the service. |
| 392 | * @hide |
| 393 | */ |
| 394 | public void destroy() { |
| 395 | nativeDestroy(); |
| 396 | mCloseGuard.close(); |
| 397 | } |
| 398 | |
| 399 | /** |
| 400 | * Returns true if this object holds a valid surface. |
| 401 | * |
| 402 | * @return True if it holds a physical surface, so lockCanvas() will succeed. |
| 403 | * Otherwise returns false. |
| 404 | */ |
| 405 | public boolean isValid() { |
| 406 | return nativeIsValid(); |
| 407 | } |
| 408 | |
| 409 | /** |
| 410 | * Gets the generation number of this surface, incremented each time |
| 411 | * the native surface contained within this object changes. |
| 412 | * |
| 413 | * @return The current generation number. |
| 414 | * @hide |
| 415 | */ |
| 416 | public int getGenerationId() { |
| 417 | return mGenerationId; |
| 418 | } |
| 419 | |
| 420 | /** |
| 421 | * Returns true if the consumer of this Surface is running behind the producer. |
| 422 | * |
| 423 | * @return True if the consumer is more than one buffer ahead of the producer. |
| 424 | * @hide |
| 425 | */ |
| 426 | public boolean isConsumerRunningBehind() { |
| 427 | return nativeIsConsumerRunningBehind(); |
| 428 | } |
| 429 | |
| 430 | /** |
| 431 | * Gets a {@link Canvas} for drawing into this surface. |
| 432 | * |
| 433 | * After drawing into the provided {@link Canvas}, the caller should |
| 434 | * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. |
| 435 | * |
| 436 | * @param dirty A rectangle that represents the dirty region that the caller wants |
| 437 | * to redraw. This function may choose to expand the dirty rectangle if for example |
| 438 | * the surface has been resized or if the previous contents of the surface were |
| 439 | * not available. The caller should redraw the entire dirty region as represented |
| 440 | * by the contents of the dirty rect upon return from this function. |
| 441 | * The caller may also pass <code>null</code> instead, in the case where the |
| 442 | * entire surface should be redrawn. |
| 443 | * @return A canvas for drawing into the surface. |
| 444 | */ |
| 445 | public Canvas lockCanvas(Rect dirty) |
| 446 | throws OutOfResourcesException, IllegalArgumentException { |
| 447 | return nativeLockCanvas(dirty); |
| 448 | } |
| 449 | |
| 450 | /** |
| 451 | * Posts the new contents of the {@link Canvas} to the surface and |
| 452 | * releases the {@link Canvas}. |
| 453 | * |
| 454 | * @param canvas The canvas previously obtained from {@link #lockCanvas}. |
| 455 | */ |
| 456 | public void unlockCanvasAndPost(Canvas canvas) { |
| 457 | nativeUnlockCanvasAndPost(canvas); |
| 458 | } |
| 459 | |
| 460 | /** |
| 461 | * @deprecated This API has been removed and is not supported. Do not use. |
| 462 | */ |
| 463 | @Deprecated |
| 464 | public void unlockCanvas(Canvas canvas) { |
| 465 | throw new UnsupportedOperationException(); |
| 466 | } |
| 467 | |
| 468 | /** |
| 469 | * Sets the translator used to scale canvas's width/height in compatibility |
| 470 | * mode. |
| 471 | */ |
| 472 | void setCompatibilityTranslator(Translator translator) { |
| 473 | if (translator != null) { |
| 474 | float appScale = translator.applicationScale; |
| 475 | mCompatibleMatrix = new Matrix(); |
| 476 | mCompatibleMatrix.setScale(appScale, appScale); |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | /** |
| 481 | * Like {@link #screenshot(int, int, int, int)} but includes all |
| 482 | * Surfaces in the screenshot. |
| 483 | * |
| 484 | * @hide |
| 485 | */ |
| 486 | public static Bitmap screenshot(int width, int height) { |
| 487 | // TODO: should take the display as a parameter |
| 488 | IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN); |
| 489 | return nativeScreenshot(displayToken, width, height, 0, 0, true); |
| 490 | } |
| 491 | |
| 492 | /** |
| 493 | * Copy the current screen contents into a bitmap and return it. |
| 494 | * |
| 495 | * @param width The desired width of the returned bitmap; the raw |
| 496 | * screen will be scaled down to this size. |
| 497 | * @param height The desired height of the returned bitmap; the raw |
| 498 | * screen will be scaled down to this size. |
| 499 | * @param minLayer The lowest (bottom-most Z order) surface layer to |
| 500 | * include in the screenshot. |
| 501 | * @param maxLayer The highest (top-most Z order) surface layer to |
| 502 | * include in the screenshot. |
| 503 | * @return Returns a Bitmap containing the screen contents, or null |
| 504 | * if an error occurs. |
| 505 | * |
| 506 | * @hide |
| 507 | */ |
| 508 | public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) { |
| 509 | // TODO: should take the display as a parameter |
| 510 | IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN); |
| 511 | return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false); |
| 512 | } |
| 513 | |
| 514 | /* |
| 515 | * set surface parameters. |
| 516 | * needs to be inside open/closeTransaction block |
| 517 | */ |
| 518 | |
| 519 | /** start a transaction @hide */ |
| 520 | public static void openTransaction() { |
| 521 | nativeOpenTransaction(); |
| 522 | } |
| 523 | |
| 524 | /** end a transaction @hide */ |
| 525 | public static void closeTransaction() { |
| 526 | nativeCloseTransaction(); |
| 527 | } |
| 528 | |
Jamie Gennis | b6ce6e4 | 2012-10-15 19:14:58 -0700 | [diff] [blame] | 529 | /** flag the transaction as an animation @hide */ |
| 530 | public static void setAnimationTransaction() { |
| 531 | nativeSetAnimationTransaction(); |
| 532 | } |
| 533 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 534 | /** @hide */ |
| 535 | public void setLayer(int zorder) { |
| 536 | nativeSetLayer(zorder); |
| 537 | } |
| 538 | |
| 539 | /** @hide */ |
| 540 | public void setPosition(int x, int y) { |
| 541 | nativeSetPosition((float)x, (float)y); |
| 542 | } |
| 543 | |
| 544 | /** @hide */ |
| 545 | public void setPosition(float x, float y) { |
| 546 | nativeSetPosition(x, y); |
| 547 | } |
| 548 | |
| 549 | /** @hide */ |
| 550 | public void setSize(int w, int h) { |
| 551 | nativeSetSize(w, h); |
| 552 | } |
| 553 | |
| 554 | /** @hide */ |
| 555 | public void hide() { |
| 556 | nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN); |
| 557 | } |
| 558 | |
| 559 | /** @hide */ |
| 560 | public void show() { |
| 561 | nativeSetFlags(0, SURFACE_HIDDEN); |
| 562 | } |
| 563 | |
| 564 | /** @hide */ |
| 565 | public void setTransparentRegionHint(Region region) { |
| 566 | nativeSetTransparentRegionHint(region); |
| 567 | } |
| 568 | |
| 569 | /** @hide */ |
| 570 | public void setAlpha(float alpha) { |
| 571 | nativeSetAlpha(alpha); |
| 572 | } |
| 573 | |
| 574 | /** @hide */ |
| 575 | public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) { |
| 576 | nativeSetMatrix(dsdx, dtdx, dsdy, dtdy); |
| 577 | } |
| 578 | |
| 579 | /** @hide */ |
| 580 | public void setFlags(int flags, int mask) { |
| 581 | nativeSetFlags(flags, mask); |
| 582 | } |
| 583 | |
| 584 | /** @hide */ |
| 585 | public void setWindowCrop(Rect crop) { |
| 586 | nativeSetWindowCrop(crop); |
| 587 | } |
| 588 | |
| 589 | /** @hide */ |
| 590 | public void setLayerStack(int layerStack) { |
| 591 | nativeSetLayerStack(layerStack); |
| 592 | } |
| 593 | |
| 594 | /** @hide */ |
| 595 | public static IBinder getBuiltInDisplay(int builtInDisplayId) { |
| 596 | return nativeGetBuiltInDisplay(builtInDisplayId); |
| 597 | } |
| 598 | |
| 599 | /** @hide */ |
Jamie Gennis | 7bbf816 | 2012-10-19 18:29:29 -0700 | [diff] [blame] | 600 | public static IBinder createDisplay(String name, boolean secure) { |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 601 | if (name == null) { |
| 602 | throw new IllegalArgumentException("name must not be null"); |
| 603 | } |
Jamie Gennis | 7bbf816 | 2012-10-19 18:29:29 -0700 | [diff] [blame] | 604 | return nativeCreateDisplay(name, secure); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 605 | } |
| 606 | |
| 607 | /** @hide */ |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 608 | public static void setDisplaySurface(IBinder displayToken, Surface surface) { |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 609 | if (displayToken == null) { |
| 610 | throw new IllegalArgumentException("displayToken must not be null"); |
| 611 | } |
Jeff Brown | cbad976 | 2012-09-04 21:57:59 -0700 | [diff] [blame] | 612 | nativeSetDisplaySurface(displayToken, surface); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 613 | } |
| 614 | |
| 615 | /** @hide */ |
| 616 | public static void setDisplayLayerStack(IBinder displayToken, int layerStack) { |
| 617 | if (displayToken == null) { |
| 618 | throw new IllegalArgumentException("displayToken must not be null"); |
| 619 | } |
| 620 | nativeSetDisplayLayerStack(displayToken, layerStack); |
| 621 | } |
| 622 | |
| 623 | /** @hide */ |
Mathias Agopian | 63f1c43 | 2012-09-04 19:29:13 -0700 | [diff] [blame] | 624 | public static void setDisplayProjection(IBinder displayToken, |
| 625 | int orientation, Rect layerStackRect, Rect displayRect) { |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 626 | if (displayToken == null) { |
| 627 | throw new IllegalArgumentException("displayToken must not be null"); |
| 628 | } |
Mathias Agopian | 63f1c43 | 2012-09-04 19:29:13 -0700 | [diff] [blame] | 629 | if (layerStackRect == null) { |
| 630 | throw new IllegalArgumentException("layerStackRect must not be null"); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 631 | } |
Mathias Agopian | 63f1c43 | 2012-09-04 19:29:13 -0700 | [diff] [blame] | 632 | if (displayRect == null) { |
| 633 | throw new IllegalArgumentException("displayRect must not be null"); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 634 | } |
Mathias Agopian | 63f1c43 | 2012-09-04 19:29:13 -0700 | [diff] [blame] | 635 | nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect); |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 636 | } |
| 637 | |
| 638 | /** @hide */ |
| 639 | public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) { |
| 640 | if (displayToken == null) { |
| 641 | throw new IllegalArgumentException("displayToken must not be null"); |
| 642 | } |
| 643 | if (outInfo == null) { |
| 644 | throw new IllegalArgumentException("outInfo must not be null"); |
| 645 | } |
| 646 | return nativeGetDisplayInfo(displayToken, outInfo); |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 647 | } |
| 648 | |
Jeff Brown | 9e316a1 | 2012-10-08 19:17:06 -0700 | [diff] [blame] | 649 | /** @hide */ |
| 650 | public static void blankDisplay(IBinder displayToken) { |
| 651 | if (displayToken == null) { |
| 652 | throw new IllegalArgumentException("displayToken must not be null"); |
| 653 | } |
| 654 | nativeBlankDisplay(displayToken); |
| 655 | } |
| 656 | |
| 657 | /** @hide */ |
| 658 | public static void unblankDisplay(IBinder displayToken) { |
| 659 | if (displayToken == null) { |
| 660 | throw new IllegalArgumentException("displayToken must not be null"); |
| 661 | } |
| 662 | nativeUnblankDisplay(displayToken); |
| 663 | } |
| 664 | |
Mitsuru Oshima | 38ed7d77 | 2009-07-21 14:39:34 -0700 | [diff] [blame] | 665 | /** |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 666 | * Copy another surface to this one. This surface now holds a reference |
| 667 | * to the same data as the original surface, and is -not- the owner. |
Dianne Hackborn | 61566cc | 2011-12-02 23:31:52 -0800 | [diff] [blame] | 668 | * This is for use by the window manager when returning a window surface |
| 669 | * back from a client, converting it from the representation being managed |
| 670 | * by the window manager to the representation the client uses to draw |
| 671 | * in to it. |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 672 | * @hide |
| 673 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 674 | public void copyFrom(Surface other) { |
| 675 | if (other == null) { |
| 676 | throw new IllegalArgumentException("other must not be null"); |
| 677 | } |
| 678 | if (other != this) { |
| 679 | nativeCopyFrom(other); |
| 680 | } |
| 681 | } |
Dianne Hackborn | 61566cc | 2011-12-02 23:31:52 -0800 | [diff] [blame] | 682 | |
| 683 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 684 | * Transfer the native state from 'other' to this surface, releasing it |
| 685 | * from 'other'. This is for use in the client side for drawing into a |
Dianne Hackborn | 61566cc | 2011-12-02 23:31:52 -0800 | [diff] [blame] | 686 | * surface; not guaranteed to work on the window manager side. |
| 687 | * This is for use by the client to move the underlying surface from |
| 688 | * one Surface object to another, in particular in SurfaceFlinger. |
| 689 | * @hide. |
| 690 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 691 | public void transferFrom(Surface other) { |
| 692 | if (other == null) { |
| 693 | throw new IllegalArgumentException("other must not be null"); |
| 694 | } |
| 695 | if (other != this) { |
| 696 | nativeTransferFrom(other); |
| 697 | } |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 698 | } |
| 699 | |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 700 | @Override |
| 701 | public int describeContents() { |
| 702 | return 0; |
| 703 | } |
| 704 | |
| 705 | public void readFromParcel(Parcel source) { |
| 706 | if (source == null) { |
| 707 | throw new IllegalArgumentException("source must not be null"); |
| 708 | } |
| 709 | |
| 710 | mName = source.readString(); |
| 711 | nativeReadFromParcel(source); |
| 712 | } |
| 713 | |
| 714 | @Override |
| 715 | public void writeToParcel(Parcel dest, int flags) { |
| 716 | if (dest == null) { |
| 717 | throw new IllegalArgumentException("dest must not be null"); |
| 718 | } |
| 719 | |
| 720 | dest.writeString(mName); |
| 721 | nativeWriteToParcel(dest); |
| 722 | if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) { |
| 723 | release(); |
| 724 | } |
| 725 | } |
| 726 | |
| 727 | @Override |
| 728 | public String toString() { |
| 729 | return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")"; |
| 730 | } |
| 731 | |
| 732 | private static void checkHeadless() { |
| 733 | if (HEADLESS) { |
| 734 | throw new UnsupportedOperationException("Device is headless"); |
| 735 | } |
| 736 | } |
Mathias Agopian | c14bacf | 2012-04-23 18:23:08 -0700 | [diff] [blame] | 737 | |
| 738 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 739 | * Exception thrown when a surface couldn't be created or resized. |
| 740 | */ |
| 741 | public static class OutOfResourcesException extends Exception { |
| 742 | public OutOfResourcesException() { |
| 743 | } |
| 744 | |
| 745 | public OutOfResourcesException(String name) { |
| 746 | super(name); |
| 747 | } |
| 748 | } |
| 749 | |
| 750 | /** |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 751 | * Describes the properties of a physical display known to surface flinger. |
Mathias Agopian | c14bacf | 2012-04-23 18:23:08 -0700 | [diff] [blame] | 752 | * @hide |
| 753 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 754 | public static final class PhysicalDisplayInfo { |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 755 | public int width; |
| 756 | public int height; |
| 757 | public float refreshRate; |
| 758 | public float density; |
| 759 | public float xDpi; |
| 760 | public float yDpi; |
Jamie Gennis | 95429c3 | 2012-10-22 15:30:42 -0700 | [diff] [blame] | 761 | public boolean secure; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 762 | |
| 763 | public PhysicalDisplayInfo() { |
| 764 | } |
| 765 | |
| 766 | public PhysicalDisplayInfo(PhysicalDisplayInfo other) { |
| 767 | copyFrom(other); |
| 768 | } |
| 769 | |
| 770 | @Override |
| 771 | public boolean equals(Object o) { |
| 772 | return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o); |
| 773 | } |
| 774 | |
| 775 | public boolean equals(PhysicalDisplayInfo other) { |
| 776 | return other != null |
| 777 | && width == other.width |
| 778 | && height == other.height |
| 779 | && refreshRate == other.refreshRate |
| 780 | && density == other.density |
| 781 | && xDpi == other.xDpi |
Jamie Gennis | 95429c3 | 2012-10-22 15:30:42 -0700 | [diff] [blame] | 782 | && yDpi == other.yDpi |
| 783 | && secure == other.secure; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 784 | } |
| 785 | |
| 786 | @Override |
| 787 | public int hashCode() { |
| 788 | return 0; // don't care |
| 789 | } |
| 790 | |
| 791 | public void copyFrom(PhysicalDisplayInfo other) { |
| 792 | width = other.width; |
| 793 | height = other.height; |
| 794 | refreshRate = other.refreshRate; |
| 795 | density = other.density; |
| 796 | xDpi = other.xDpi; |
| 797 | yDpi = other.yDpi; |
Jamie Gennis | 95429c3 | 2012-10-22 15:30:42 -0700 | [diff] [blame] | 798 | secure = other.secure; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 799 | } |
| 800 | |
| 801 | // For debugging purposes |
| 802 | @Override |
| 803 | public String toString() { |
| 804 | return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, " |
Jamie Gennis | 95429c3 | 2012-10-22 15:30:42 -0700 | [diff] [blame] | 805 | + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure |
| 806 | + "}"; |
Jeff Brown | 4ed8fe7 | 2012-08-30 18:18:29 -0700 | [diff] [blame] | 807 | } |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 808 | } |
Mathias Agopian | c14bacf | 2012-04-23 18:23:08 -0700 | [diff] [blame] | 809 | |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 810 | /** |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 811 | * A Canvas class that can handle the compatibility mode. |
| 812 | * This does two things differently. |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 813 | * <ul> |
Mathias Agopian | b923066 | 2011-08-03 14:44:48 -0700 | [diff] [blame] | 814 | * <li>Returns the width and height of the target metrics, rather than |
| 815 | * native. For example, the canvas returns 320x480 even if an app is running |
| 816 | * in WVGA high density. |
| 817 | * <li>Scales the matrix in setMatrix by the application scale, except if |
| 818 | * the matrix looks like obtained from getMatrix. This is a hack to handle |
| 819 | * the case that an application uses getMatrix to keep the original matrix, |
| 820 | * set matrix of its own, then set the original matrix back. There is no |
| 821 | * perfect solution that works for all cases, and there are a lot of cases |
| 822 | * that this model does not work, but we hope this works for many apps. |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 823 | * </ul> |
| 824 | */ |
Jeff Brown | 64a55af | 2012-08-26 02:47:39 -0700 | [diff] [blame] | 825 | private final class CompatibleCanvas extends Canvas { |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 826 | // A temp matrix to remember what an application obtained via {@link getMatrix} |
| 827 | private Matrix mOrigMatrix = null; |
| 828 | |
| 829 | @Override |
| 830 | public int getWidth() { |
Dianne Hackborn | 5be8de3 | 2011-05-24 18:11:57 -0700 | [diff] [blame] | 831 | int w = super.getWidth(); |
| 832 | if (mCompatibilityTranslator != null) { |
| 833 | w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f); |
| 834 | } |
| 835 | return w; |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 836 | } |
| 837 | |
| 838 | @Override |
| 839 | public int getHeight() { |
Dianne Hackborn | 5be8de3 | 2011-05-24 18:11:57 -0700 | [diff] [blame] | 840 | int h = super.getHeight(); |
| 841 | if (mCompatibilityTranslator != null) { |
| 842 | h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f); |
| 843 | } |
| 844 | return h; |
Mitsuru Oshima | 240f8a7 | 2009-07-22 20:39:14 -0700 | [diff] [blame] | 845 | } |
| 846 | |
| 847 | @Override |
| 848 | public void setMatrix(Matrix matrix) { |
| 849 | if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) { |
| 850 | // don't scale the matrix if it's not compatibility mode, or |
| 851 | // the matrix was obtained from getMatrix. |
| 852 | super.setMatrix(matrix); |
| 853 | } else { |
| 854 | Matrix m = new Matrix(mCompatibleMatrix); |
| 855 | m.preConcat(matrix); |
| 856 | super.setMatrix(m); |
| 857 | } |
| 858 | } |
| 859 | |
| 860 | @Override |
| 861 | public void getMatrix(Matrix m) { |
| 862 | super.getMatrix(m); |
| 863 | if (mOrigMatrix == null) { |
| 864 | mOrigMatrix = new Matrix(); |
| 865 | } |
| 866 | mOrigMatrix.set(m); |
| 867 | } |
Romain Guy | d10cd57 | 2010-10-10 13:33:22 -0700 | [diff] [blame] | 868 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 869 | } |