Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb977022 authored by Emilian Peev's avatar Emilian Peev
Browse files

Camera: Release internal capture request surfaces

Binder generated capture requests can also include
a set of output Surfaces. The surfaces in this scenario
are internal and the request needs to ensure that they
get released accordingly.
Additionally ensure that incoming advanced extension
client surface are explicitly released after the
session close.

API-Coverage-Bug: 328622115
Bug: 324071855
Test: #testRepeatingAndCaptureCombined with strict mode enabled
didn't generate any further Surface release warnings

Change-Id: I6e050765ae0344fcd6c33636f420377626107a51
parent db0932b5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19694,6 +19694,7 @@ package android.hardware.camera2 {
  public final class CaptureRequest extends android.hardware.camera2.CameraMetadata<android.hardware.camera2.CaptureRequest.Key<?>> implements android.os.Parcelable {
    method public int describeContents();
    method @FlaggedApi("com.android.internal.camera.flags.surface_leak_fix") protected void finalize();
    method @Nullable public <T> T get(android.hardware.camera2.CaptureRequest.Key<T>);
    method @NonNull public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getKeys();
    method @Nullable public Object getTag();
+16 −0
Original line number Diff line number Diff line
@@ -309,6 +309,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>

    private Object mUserTag;

    private boolean mReleaseSurfaces = false;

    /**
     * Construct empty request.
     *
@@ -610,6 +612,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
            Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader(),
                    Surface.class);
            if (parcelableArray != null) {
                if (Flags.surfaceLeakFix()) {
                    mReleaseSurfaces = true;
                }
                for (Parcelable p : parcelableArray) {
                    Surface s = (Surface) p;
                    mSurfaceSet.add(s);
@@ -792,6 +797,17 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
        }
    }

    @SuppressWarnings("Finalize")
    @FlaggedApi(Flags.FLAG_SURFACE_LEAK_FIX)
    @Override
    protected void finalize() {
        if (mReleaseSurfaces) {
            for (Surface s : mSurfaceSet) {
                s.release();
            }
        }
    }

    /**
     * A builder for capture requests.
     *
+20 −0
Original line number Diff line number Diff line
@@ -363,11 +363,20 @@ public abstract class SessionProcessor {

    private final class SessionProcessorImpl extends ISessionProcessorImpl.Stub {
        private long mVendorId = -1;
        OutputSurface mImageCaptureSurface;
        OutputSurface mPreviewSurface;
        OutputSurface mPostviewSurface;

        @Override
        public CameraSessionConfig initSession(IBinder token, String cameraId,
                Map<String, CameraMetadataNative> charsMap, OutputSurface previewSurface,
                OutputSurface imageCaptureSurface, OutputSurface postviewSurface)
                throws RemoteException {
            if (Flags.surfaceLeakFix()) {
                mPreviewSurface = previewSurface;
                mPostviewSurface = postviewSurface;
                mImageCaptureSurface = imageCaptureSurface;
            }
            ExtensionConfiguration config = SessionProcessor.this.initSession(token, cameraId,
                    new CharacteristicsMap(charsMap),
                    new CameraOutputSurface(previewSurface),
@@ -390,6 +399,17 @@ public abstract class SessionProcessor {
        @Override
        public void deInitSession(IBinder token) throws RemoteException {
            SessionProcessor.this.deInitSession(token);
            if (Flags.surfaceLeakFix()) {
                if ((mPreviewSurface != null) && (mPreviewSurface.surface != null)) {
                    mPreviewSurface.surface.release();
                }
                if ((mImageCaptureSurface != null) && (mImageCaptureSurface.surface != null)) {
                    mImageCaptureSurface.surface.release();
                }
                if ((mPostviewSurface != null) && (mPostviewSurface.surface != null)) {
                    mPostviewSurface.surface.release();
                }
            }
        }

        @Override
+24 −11
Original line number Diff line number Diff line
@@ -1566,6 +1566,10 @@ public class CameraExtensionsProxyService extends Service {
        private String mCameraId = null;
        private IBinder mToken;

        OutputSurfaceImplStub mOutputPreviewSurfaceImpl;
        OutputSurfaceImplStub mOutputImageCaptureSurfaceImpl;
        OutputSurfaceImplStub mOutputPostviewSurfaceImpl;

        public SessionProcessorImplStub(SessionProcessorImpl sessionProcessor) {
            mSessionProcessor = sessionProcessor;
        }
@@ -1574,21 +1578,18 @@ public class CameraExtensionsProxyService extends Service {
        public CameraSessionConfig initSession(IBinder token, String cameraId,
                Map<String, CameraMetadataNative> charsMapNative, OutputSurface previewSurface,
                OutputSurface imageCaptureSurface, OutputSurface postviewSurface) {
            OutputSurfaceImplStub outputPreviewSurfaceImpl =
                    new OutputSurfaceImplStub(previewSurface);
            OutputSurfaceImplStub outputImageCaptureSurfaceImpl =
                    new OutputSurfaceImplStub(imageCaptureSurface);
            OutputSurfaceImplStub outputPostviewSurfaceImpl =
                    new OutputSurfaceImplStub(postviewSurface);
            mOutputPreviewSurfaceImpl = new OutputSurfaceImplStub(previewSurface);
            mOutputImageCaptureSurfaceImpl = new OutputSurfaceImplStub(imageCaptureSurface);
            mOutputPostviewSurfaceImpl = new OutputSurfaceImplStub(postviewSurface);

            Camera2SessionConfigImpl sessionConfig;

            if (LATENCY_IMPROVEMENTS_SUPPORTED) {
                OutputSurfaceConfigurationImplStub outputSurfaceConfigs =
                        new OutputSurfaceConfigurationImplStub(outputPreviewSurfaceImpl,
                        new OutputSurfaceConfigurationImplStub(mOutputPreviewSurfaceImpl,
                        // Image Analysis Output is currently only supported in CameraX
                        outputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/,
                        outputPostviewSurfaceImpl);
                        mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/,
                        mOutputPostviewSurfaceImpl);

                sessionConfig = mSessionProcessor.initSession(cameraId,
                        getCharacteristicsMap(charsMapNative),
@@ -1596,8 +1597,8 @@ public class CameraExtensionsProxyService extends Service {
            } else {
                sessionConfig = mSessionProcessor.initSession(cameraId,
                        getCharacteristicsMap(charsMapNative),
                        getApplicationContext(), outputPreviewSurfaceImpl,
                        outputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/);
                        getApplicationContext(), mOutputPreviewSurfaceImpl,
                        mOutputImageCaptureSurfaceImpl, null /*imageAnalysisSurfaceConfig*/);
            }

            List<Camera2OutputConfigImpl> outputConfigs = sessionConfig.getOutputConfigs();
@@ -1632,6 +1633,18 @@ public class CameraExtensionsProxyService extends Service {
        public void deInitSession(IBinder token) {
            CameraExtensionsProxyService.unregisterDeathRecipient(mToken, this);
            mSessionProcessor.deInitSession();

            if (Flags.surfaceLeakFix()) {
                if (mOutputImageCaptureSurfaceImpl.mSurface != null) {
                    mOutputImageCaptureSurfaceImpl.mSurface.release();
                }
                if (mOutputPreviewSurfaceImpl.mSurface != null) {
                    mOutputPreviewSurfaceImpl.mSurface.release();
                }
                if (mOutputPostviewSurfaceImpl.mSurface != null) {
                    mOutputPostviewSurfaceImpl.mSurface.release();
                }
            }
        }

        @Override