Merge "Add fence support in ImageWriter class."
This commit is contained in:
@@ -17054,6 +17054,14 @@ package android.hardware {
|
||||
field public static final int MICROPHONE = 1; // 0x1
|
||||
}
|
||||
|
||||
public final class SyncFence implements java.io.Closeable android.os.Parcelable {
|
||||
method public void close() throws java.io.IOException;
|
||||
method public int describeContents();
|
||||
method public boolean isValid();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.SyncFence> CREATOR;
|
||||
}
|
||||
|
||||
public final class TriggerEvent {
|
||||
field public android.hardware.Sensor sensor;
|
||||
field public long timestamp;
|
||||
@@ -20829,6 +20837,7 @@ package android.media {
|
||||
method public abstract void close();
|
||||
method public android.graphics.Rect getCropRect();
|
||||
method public long getDataSpace();
|
||||
method @NonNull public android.hardware.SyncFence getFence() throws java.io.IOException;
|
||||
method public abstract int getFormat();
|
||||
method @Nullable public android.hardware.HardwareBuffer getHardwareBuffer();
|
||||
method public abstract int getHeight();
|
||||
@@ -20837,6 +20846,7 @@ package android.media {
|
||||
method public abstract int getWidth();
|
||||
method public void setCropRect(android.graphics.Rect);
|
||||
method public void setDataSpace(long);
|
||||
method public void setFence(@NonNull android.hardware.SyncFence) throws java.io.IOException;
|
||||
method public void setTimestamp(long);
|
||||
}
|
||||
|
||||
|
||||
141
core/java/android/hardware/SyncFence.java
Normal file
141
core/java/android/hardware/SyncFence.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Copyright (C) 2022 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.hardware;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Parcel;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A SyncFence represents a synchronization primitive which signals when hardware buffers have
|
||||
* completed work on a particular resource.
|
||||
*
|
||||
* <p>For example, a GPU rendering to a framebuffer may generate a synchronization fence,
|
||||
* e.g., a VkFence, which signals when rendering has completed.
|
||||
*
|
||||
* Once the fence signals, then the backing storage for the framebuffer may be safely read from,
|
||||
* such as for display or for media encoding.</p>
|
||||
*
|
||||
* @see <a href="https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/vkCreateFence.html">
|
||||
* VkFence</a>
|
||||
*/
|
||||
public final class SyncFence implements Closeable, Parcelable {
|
||||
private static final String TAG = "SyncFence";
|
||||
|
||||
/**
|
||||
* Wrapped {@link android.os.ParcelFileDescriptor}.
|
||||
*/
|
||||
private ParcelFileDescriptor mWrapped;
|
||||
|
||||
private SyncFence(@NonNull ParcelFileDescriptor wrapped) {
|
||||
mWrapped = wrapped;
|
||||
}
|
||||
|
||||
/***
|
||||
* Create an empty SyncFence
|
||||
*
|
||||
* @return a SyncFence with invalid fence
|
||||
* @hide
|
||||
*/
|
||||
public static @NonNull SyncFence createEmpty() {
|
||||
return new SyncFence(ParcelFileDescriptor.adoptFd(-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new SyncFence wrapped around another descriptor. By default, all method calls are
|
||||
* delegated to the wrapped descriptor.
|
||||
*
|
||||
* @param wrapped The descriptor to be wrapped.
|
||||
* @hide
|
||||
*/
|
||||
public static @NonNull SyncFence create(@NonNull ParcelFileDescriptor wrapped) {
|
||||
return new SyncFence(wrapped);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a dup'd ParcelFileDescriptor from the SyncFence ParcelFileDescriptor.
|
||||
* @hide
|
||||
*/
|
||||
public @NonNull ParcelFileDescriptor getFdDup() throws IOException {
|
||||
return mWrapped.dup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the SyncFile object is valid.
|
||||
*
|
||||
* @return {@code true} if the file descriptor represents a valid, open file;
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return mWrapped.getFileDescriptor().valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the SyncFence. This implementation closes the underlying OS resources allocated
|
||||
* this stream.
|
||||
*
|
||||
* @throws IOException If an error occurs attempting to close this SyncFence.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (mWrapped != null) {
|
||||
try {
|
||||
mWrapped.close();
|
||||
} finally {
|
||||
// success
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return mWrapped.describeContents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten this object into a Parcel.
|
||||
*
|
||||
* @param out The Parcel in which the object should be written.
|
||||
* @param flags Additional flags about how the object should be written.
|
||||
* May be {@code 0} or {@link #PARCELABLE_WRITE_RETURN_VALUE}
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel out, int flags) {
|
||||
try {
|
||||
mWrapped.writeToParcel(out, flags);
|
||||
} finally {
|
||||
// success
|
||||
}
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<SyncFence> CREATOR =
|
||||
new Parcelable.Creator<SyncFence>() {
|
||||
@Override
|
||||
public SyncFence createFromParcel(Parcel in) {
|
||||
return new SyncFence(ParcelFileDescriptor.CREATOR.createFromParcel(in));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SyncFence[] newArray(int size) {
|
||||
return new SyncFence[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
|
||||
import android.content.Context;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.SyncFence;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
@@ -58,7 +59,6 @@ import android.media.ImageReader;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
@@ -822,12 +822,13 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
|
||||
|
||||
ParcelImage parcelImage = new ParcelImage();
|
||||
parcelImage.buffer = img.getHardwareBuffer();
|
||||
if (img.getFenceFd() >= 0) {
|
||||
try {
|
||||
parcelImage.fence = ParcelFileDescriptor.fromFd(img.getFenceFd());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"Failed to parcel buffer fence!");
|
||||
try {
|
||||
SyncFence fd = img.getFence();
|
||||
if (fd.isValid()) {
|
||||
parcelImage.fence = fd.getFdDup();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to parcel buffer fence!");
|
||||
}
|
||||
parcelImage.width = img.getWidth();
|
||||
parcelImage.height = img.getHeight();
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
|
||||
package android.hardware.camera2.impl;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.content.Context;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.hardware.SyncFence;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
import android.hardware.camera2.CameraCharacteristics;
|
||||
@@ -30,6 +34,7 @@ import android.hardware.camera2.CameraManager;
|
||||
import android.hardware.camera2.CaptureFailure;
|
||||
import android.hardware.camera2.CaptureRequest;
|
||||
import android.hardware.camera2.CaptureResult;
|
||||
import android.hardware.camera2.TotalCaptureResult;
|
||||
import android.hardware.camera2.extension.CaptureBundle;
|
||||
import android.hardware.camera2.extension.CaptureStageImpl;
|
||||
import android.hardware.camera2.extension.ICaptureProcessorImpl;
|
||||
@@ -39,7 +44,6 @@ import android.hardware.camera2.extension.IPreviewExtenderImpl;
|
||||
import android.hardware.camera2.extension.IProcessResultImpl;
|
||||
import android.hardware.camera2.extension.IRequestUpdateProcessorImpl;
|
||||
import android.hardware.camera2.extension.ParcelImage;
|
||||
import android.hardware.camera2.TotalCaptureResult;
|
||||
import android.hardware.camera2.params.DynamicRangeProfiles;
|
||||
import android.hardware.camera2.params.ExtensionSessionConfiguration;
|
||||
import android.hardware.camera2.params.OutputConfiguration;
|
||||
@@ -51,11 +55,7 @@ import android.media.ImageWriter;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.util.Log;
|
||||
import android.util.LongSparseArray;
|
||||
import android.util.Pair;
|
||||
@@ -1768,12 +1768,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
||||
private static ParcelImage initializeParcelImage(Image img) {
|
||||
ParcelImage parcelImage = new ParcelImage();
|
||||
parcelImage.buffer = img.getHardwareBuffer();
|
||||
if (img.getFenceFd() >= 0) {
|
||||
try {
|
||||
parcelImage.fence = ParcelFileDescriptor.fromFd(img.getFenceFd());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"Failed to parcel buffer fence!");
|
||||
try {
|
||||
SyncFence fd = img.getFence();
|
||||
if (fd.isValid()) {
|
||||
parcelImage.fence = fd.getFdDup();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to parcel buffer fence!");
|
||||
}
|
||||
parcelImage.width = img.getWidth();
|
||||
parcelImage.height = img.getHeight();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TestApi;
|
||||
@@ -24,7 +25,9 @@ import android.graphics.Rect;
|
||||
import android.hardware.DataSpace;
|
||||
import android.hardware.DataSpace.NamedDataSpace;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.hardware.SyncFence;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
@@ -223,12 +226,17 @@ public abstract class Image implements AutoCloseable {
|
||||
public abstract int getScalingMode();
|
||||
|
||||
/**
|
||||
* Get the fence file descriptor associated with this frame.
|
||||
* @return The fence file descriptor for this frame.
|
||||
* @hide
|
||||
* Get the SyncFence object associated with this frame.
|
||||
*
|
||||
* <p>This function returns an invalid SyncFence after {@link #getPlanes()} on the image
|
||||
* dequeued from {@link ImageWriter} via {@link ImageWriter#dequeueInputImage()}.</p>
|
||||
*
|
||||
* @return The SyncFence for this frame.
|
||||
* @throws IOException if there is an error when a SyncFence object returns.
|
||||
* @see android.hardware.SyncFence
|
||||
*/
|
||||
public int getFenceFd() {
|
||||
return -1;
|
||||
public @NonNull SyncFence getFence() throws IOException {
|
||||
return SyncFence.createEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,6 +291,17 @@ public abstract class Image implements AutoCloseable {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fence file descriptor with this frame.
|
||||
* @param fence The fence file descriptor to be set for this frame.
|
||||
* @throws IOException if there is an error when setting a SyncFence.
|
||||
* @see android.hardware.SyncFence
|
||||
*/
|
||||
public void setFence(@NonNull SyncFence fence) throws IOException {
|
||||
throwISEIfImageIsInvalid();
|
||||
return;
|
||||
}
|
||||
|
||||
private @NamedDataSpace long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,13 +27,16 @@ import android.hardware.DataSpace;
|
||||
import android.hardware.DataSpace.NamedDataSpace;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.hardware.HardwareBuffer.Usage;
|
||||
import android.hardware.SyncFence;
|
||||
import android.hardware.camera2.MultiResolutionImageReader;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.view.Surface;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@@ -1219,9 +1222,15 @@ public class ImageReader implements AutoCloseable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFenceFd() {
|
||||
public SyncFence getFence() throws IOException {
|
||||
throwISEIfImageIsInvalid();
|
||||
return nativeGetFenceFd();
|
||||
// duplicate ParcelFileDescriptor because native still retains the fence ownership.
|
||||
int fence = nativeGetFenceFd();
|
||||
if (fence != -1) {
|
||||
return SyncFence.create(ParcelFileDescriptor.fromFd(nativeGetFenceFd()));
|
||||
} else {
|
||||
return SyncFence.createEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,16 +28,19 @@ import android.hardware.DataSpace;
|
||||
import android.hardware.DataSpace.NamedDataSpace;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.hardware.HardwareBuffer.Usage;
|
||||
import android.hardware.SyncFence;
|
||||
import android.hardware.camera2.params.StreamConfigurationMap;
|
||||
import android.hardware.camera2.utils.SurfaceUtils;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Size;
|
||||
import android.view.Surface;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
@@ -1143,6 +1146,23 @@ public class ImageWriter implements AutoCloseable {
|
||||
return nativeGetHardwareBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SyncFence getFence() throws IOException {
|
||||
throwISEIfImageIsInvalid();
|
||||
// if mNativeFenceFd is -1, the fence is closed
|
||||
if (mNativeFenceFd != -1) {
|
||||
return SyncFence.create(ParcelFileDescriptor.fromFd(mNativeFenceFd));
|
||||
} else {
|
||||
return SyncFence.createEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFence(@NonNull SyncFence fence) throws IOException {
|
||||
throwISEIfImageIsInvalid();
|
||||
nativeSetFenceFd(fence.getFdDup().detachFd());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plane[] getPlanes() {
|
||||
throwISEIfImageIsInvalid();
|
||||
@@ -1268,6 +1288,8 @@ public class ImageWriter implements AutoCloseable {
|
||||
private synchronized native int nativeGetFormat(long dataSpace);
|
||||
|
||||
private synchronized native HardwareBuffer nativeGetHardwareBuffer();
|
||||
|
||||
private synchronized native void nativeSetFenceFd(int fenceFd);
|
||||
}
|
||||
|
||||
// Native implemented ImageWriter methods.
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
#include <deque>
|
||||
|
||||
#define IMAGE_BUFFER_JNI_ID "mNativeBuffer"
|
||||
#define IMAGE_FORMAT_UNKNOWN 0 // This is the same value as ImageFormat#UNKNOWN.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
using namespace android;
|
||||
@@ -991,6 +990,11 @@ static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
|
||||
|
||||
static void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) {
|
||||
ALOGV("%s:", __FUNCTION__);
|
||||
int curtFenceFd = reinterpret_cast<jint>(
|
||||
env->GetIntField(thiz,gSurfaceImageClassInfo.mNativeFenceFd));
|
||||
if (curtFenceFd != -1) {
|
||||
close(curtFenceFd);
|
||||
}
|
||||
env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd));
|
||||
}
|
||||
|
||||
@@ -1120,6 +1124,7 @@ static JNINativeMethod gImageMethods[] = {
|
||||
{"nativeGetWidth", "()I", (void*)Image_getWidth },
|
||||
{"nativeGetHeight", "()I", (void*)Image_getHeight },
|
||||
{"nativeGetFormat", "(J)I", (void*)Image_getFormat },
|
||||
{"nativeSetFenceFd", "(I)V", (void*)Image_setFenceFd },
|
||||
{"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
|
||||
(void*)Image_getHardwareBuffer },
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user