|  | /* | 
|  | * Copyright (C) 2013 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | package android.graphics; | 
|  |  | 
|  | import android.compat.annotation.UnsupportedAppUsage; | 
|  | import android.hardware.HardwareBuffer; | 
|  | import android.os.Build; | 
|  | import android.os.Parcel; | 
|  | import android.os.Parcelable; | 
|  |  | 
|  | /** | 
|  | * Simple wrapper for the native GraphicBuffer class. | 
|  | * | 
|  | * @hide | 
|  | */ | 
|  | @SuppressWarnings("UnusedDeclaration") | 
|  | public class GraphicBuffer implements Parcelable { | 
|  | // Note: keep usage flags in sync with GraphicBuffer.h and gralloc.h | 
|  | public static final int USAGE_SW_READ_NEVER = 0x0; | 
|  | public static final int USAGE_SW_READ_RARELY = 0x2; | 
|  | public static final int USAGE_SW_READ_OFTEN = 0x3; | 
|  | public static final int USAGE_SW_READ_MASK = 0xF; | 
|  |  | 
|  | public static final int USAGE_SW_WRITE_NEVER = 0x0; | 
|  | public static final int USAGE_SW_WRITE_RARELY = 0x20; | 
|  | public static final int USAGE_SW_WRITE_OFTEN = 0x30; | 
|  | public static final int USAGE_SW_WRITE_MASK = 0xF0; | 
|  |  | 
|  | public static final int USAGE_SOFTWARE_MASK = USAGE_SW_READ_MASK | USAGE_SW_WRITE_MASK; | 
|  |  | 
|  | public static final int USAGE_PROTECTED = 0x4000; | 
|  |  | 
|  | public static final int USAGE_HW_TEXTURE = 0x100; | 
|  | public static final int USAGE_HW_RENDER = 0x200; | 
|  | public static final int USAGE_HW_2D = 0x400; | 
|  | public static final int USAGE_HW_COMPOSER = 0x800; | 
|  | public static final int USAGE_HW_VIDEO_ENCODER = 0x10000; | 
|  | public static final int USAGE_HW_MASK = 0x71F00; | 
|  |  | 
|  | private final int mWidth; | 
|  | private final int mHeight; | 
|  | private final int mFormat; | 
|  | private final int mUsage; | 
|  | // Note: do not rename, this field is used by native code | 
|  | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) | 
|  | private long mNativeObject; | 
|  |  | 
|  | // These two fields are only used by lock/unlockCanvas() | 
|  | private Canvas mCanvas; | 
|  | private int mSaveCount; | 
|  |  | 
|  | // If set to true, this GraphicBuffer instance cannot be used anymore | 
|  | private boolean mDestroyed; | 
|  |  | 
|  | /** | 
|  | * Creates new <code>GraphicBuffer</code> instance. This method will return null | 
|  | * if the buffer cannot be created. | 
|  | * | 
|  | * @param width The width in pixels of the buffer | 
|  | * @param height The height in pixels of the buffer | 
|  | * @param format The format of each pixel as specified in {@link PixelFormat} | 
|  | * @param usage Hint indicating how the buffer will be used | 
|  | * | 
|  | * @return A <code>GraphicBuffer</code> instance or null | 
|  | */ | 
|  | public static GraphicBuffer create(int width, int height, int format, int usage) { | 
|  | long nativeObject = nCreateGraphicBuffer(width, height, format, usage); | 
|  | if (nativeObject != 0) { | 
|  | return new GraphicBuffer(width, height, format, usage, nativeObject); | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Private use only. See {@link #create(int, int, int, int)}. | 
|  | */ | 
|  | @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) | 
|  | private GraphicBuffer(int width, int height, int format, int usage, long nativeObject) { | 
|  | mWidth = width; | 
|  | mHeight = height; | 
|  | mFormat = format; | 
|  | mUsage = usage; | 
|  | mNativeObject = nativeObject; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * For Bitmap until all usages are updated to AHB | 
|  | * @hide | 
|  | */ | 
|  | public static final GraphicBuffer createFromHardwareBuffer(HardwareBuffer buffer) { | 
|  | return nCreateFromHardwareBuffer(buffer); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the width of this buffer in pixels. | 
|  | */ | 
|  | public int getWidth() { | 
|  | return mWidth; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the height of this buffer in pixels. | 
|  | */ | 
|  | public int getHeight() { | 
|  | return mHeight; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the pixel format of this buffer. The pixel format must be one of | 
|  | * the formats defined in {@link PixelFormat}. | 
|  | */ | 
|  | public int getFormat() { | 
|  | return mFormat; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the usage hint set on this buffer. | 
|  | */ | 
|  | public int getUsage() { | 
|  | return mUsage; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * <p>Start editing the pixels in the buffer. A null is returned if the buffer | 
|  | * cannot be locked for editing.</p> | 
|  | * | 
|  | * <p>The content of the buffer is preserved between unlockCanvas() | 
|  | * and lockCanvas().</p> | 
|  | * | 
|  | * <p>If this method is called after {@link #destroy()}, the return value will | 
|  | * always be null.</p> | 
|  | * | 
|  | * @return A Canvas used to draw into the buffer, or null. | 
|  | * | 
|  | * @see #lockCanvas(android.graphics.Rect) | 
|  | * @see #unlockCanvasAndPost(android.graphics.Canvas) | 
|  | * @see #isDestroyed() | 
|  | */ | 
|  | public Canvas lockCanvas() { | 
|  | return lockCanvas(null); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Just like {@link #lockCanvas()} but allows specification of a dirty | 
|  | * rectangle. | 
|  | * | 
|  | * <p>If this method is called after {@link #destroy()}, the return value will | 
|  | * always be null.</p> | 
|  | * | 
|  | * @param dirty Area of the buffer that may be modified. | 
|  |  | 
|  | * @return A Canvas used to draw into the surface, or null. | 
|  | * | 
|  | * @see #lockCanvas() | 
|  | * @see #unlockCanvasAndPost(android.graphics.Canvas) | 
|  | * @see #isDestroyed() | 
|  | */ | 
|  | public Canvas lockCanvas(Rect dirty) { | 
|  | if (mDestroyed) { | 
|  | return null; | 
|  | } | 
|  |  | 
|  | if (mCanvas == null) { | 
|  | mCanvas = new Canvas(); | 
|  | } | 
|  |  | 
|  | if (nLockCanvas(mNativeObject, mCanvas, dirty)) { | 
|  | mSaveCount = mCanvas.save(); | 
|  | return mCanvas; | 
|  | } | 
|  |  | 
|  | return null; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Finish editing pixels in the buffer. | 
|  | * | 
|  | * <p>This method doesn't do anything if {@link #destroy()} was | 
|  | * previously called.</p> | 
|  | * | 
|  | * @param canvas The Canvas previously returned by lockCanvas() | 
|  | * | 
|  | * @see #lockCanvas() | 
|  | * @see #lockCanvas(android.graphics.Rect) | 
|  | * @see #isDestroyed() | 
|  | */ | 
|  | public void unlockCanvasAndPost(Canvas canvas) { | 
|  | if (!mDestroyed && mCanvas != null && canvas == mCanvas) { | 
|  | canvas.restoreToCount(mSaveCount); | 
|  | mSaveCount = 0; | 
|  |  | 
|  | nUnlockCanvasAndPost(mNativeObject, mCanvas); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Destroyes this buffer immediately. Calling this method frees up any | 
|  | * underlying native resources. After calling this method, this buffer | 
|  | * must not be used in any way ({@link #lockCanvas()} must not be called, | 
|  | * etc.) | 
|  | * | 
|  | * @see #isDestroyed() | 
|  | */ | 
|  | public void destroy() { | 
|  | if (!mDestroyed) { | 
|  | mDestroyed = true; | 
|  | nDestroyGraphicBuffer(mNativeObject); | 
|  | mNativeObject = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Indicates whether this buffer has been destroyed. A destroyed buffer | 
|  | * cannot be used in any way: locking a Canvas will return null, the buffer | 
|  | * cannot be written to a parcel, etc. | 
|  | * | 
|  | * @return True if this <code>GraphicBuffer</code> is in a destroyed state, | 
|  | *         false otherwise. | 
|  | * | 
|  | * @see #destroy() | 
|  | */ | 
|  | public boolean isDestroyed() { | 
|  | return mDestroyed; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | protected void finalize() throws Throwable { | 
|  | try { | 
|  | destroy(); | 
|  | } finally { | 
|  | super.finalize(); | 
|  | } | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int describeContents() { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Flatten this object in to a Parcel. | 
|  | * | 
|  | * <p>Calling this method will throw an <code>IllegalStateException</code> if | 
|  | * {@link #destroy()} has been previously called.</p> | 
|  | * | 
|  | * @param dest The Parcel in which the object should be written. | 
|  | * @param flags Additional flags about how the object should be written. | 
|  | *              May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. | 
|  | */ | 
|  | @Override | 
|  | public void writeToParcel(Parcel dest, int flags) { | 
|  | if (mDestroyed) { | 
|  | throw new IllegalStateException("This GraphicBuffer has been destroyed and cannot be " | 
|  | + "written to a parcel."); | 
|  | } | 
|  |  | 
|  | dest.writeInt(mWidth); | 
|  | dest.writeInt(mHeight); | 
|  | dest.writeInt(mFormat); | 
|  | dest.writeInt(mUsage); | 
|  | nWriteGraphicBufferToParcel(mNativeObject, dest); | 
|  | } | 
|  |  | 
|  | @UnsupportedAppUsage | 
|  | public static final @android.annotation.NonNull Parcelable.Creator<GraphicBuffer> CREATOR = | 
|  | new Parcelable.Creator<GraphicBuffer>() { | 
|  | public GraphicBuffer createFromParcel(Parcel in) { | 
|  | int width = in.readInt(); | 
|  | int height = in.readInt(); | 
|  | int format = in.readInt(); | 
|  | int usage = in.readInt(); | 
|  | long nativeObject = nReadGraphicBufferFromParcel(in); | 
|  | if (nativeObject != 0) { | 
|  | return new GraphicBuffer(width, height, format, usage, nativeObject); | 
|  | } | 
|  | return null; | 
|  | } | 
|  |  | 
|  | public GraphicBuffer[] newArray(int size) { | 
|  | return new GraphicBuffer[size]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | private static native long nCreateGraphicBuffer(int width, int height, int format, int usage); | 
|  | private static native void nDestroyGraphicBuffer(long nativeObject); | 
|  | private static native void nWriteGraphicBufferToParcel(long nativeObject, Parcel dest); | 
|  | private static native long nReadGraphicBufferFromParcel(Parcel in); | 
|  | private static native boolean nLockCanvas(long nativeObject, Canvas canvas, Rect dirty); | 
|  | private static native boolean nUnlockCanvasAndPost(long nativeObject, Canvas canvas); | 
|  | private static native GraphicBuffer nCreateFromHardwareBuffer(HardwareBuffer buffer); | 
|  | } |