Skip to content

Commit 14c09fa

Browse files
author
Eino-Ville Talvala
committed
Camera2: Add hidden experimental tearDown method
Bug: 18949148 Change-Id: I6264d95a26ebf51cce6114c9a86b9561f7c60ab5
1 parent eea8be5 commit 14c09fa

6 files changed

Lines changed: 90 additions & 0 deletions

File tree

core/java/android/hardware/camera2/CameraCaptureSession.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,45 @@ public abstract class CameraCaptureSession implements AutoCloseable {
138138
*/
139139
public abstract void prepare(@NonNull Surface surface) throws CameraAccessException;
140140

141+
142+
/**
143+
* <p>Free all buffers allocated for an output Surface.</p>
144+
*
145+
* <p>Normally, once allocated, the image buffers for a given output Surface remain allocated
146+
* for the lifetime of the capture session, to minimize latency of captures and to reduce
147+
* memory allocation overhead.</p>
148+
*
149+
* <p>However, in some cases, it may be desirable for allocated buffers to be freed to reduce
150+
* the application's memory consumption, if the particular output Surface will not be used by
151+
* the application for some time.</p>
152+
*
153+
* <p>The tearDown() method can be used to perform this operation. After the call finishes, all
154+
* unfilled image buffers will have been freed. Any future use of the target Surface may require
155+
* allocation of additional buffers, as if the session had just been created. Buffers being
156+
* held by the application (either explicitly as Image objects from ImageReader, or implicitly
157+
* as the current texture in a SurfaceTexture or the current contents of a RS Allocation, will
158+
* remain valid and allocated even when tearDown is invoked.</p>
159+
*
160+
* <p>A Surface that has had tearDown() called on it is eligible to have prepare() invoked on it
161+
* again even if it was used as a request target before the tearDown() call, as long as it
162+
* doesn't get used as a target of a request between the tearDown() and prepare() calls.</p>
163+
*
164+
* @param surface the output Surface for which buffers should be freed. Must be one of the
165+
* the output Surfaces used to create this session.
166+
*
167+
* @throws CameraAccessException if the camera device is no longer connected or has
168+
* encountered a fatal error.
169+
* @throws IllegalStateException if this session is no longer active, either because the session
170+
* was explicitly closed, a new session has been created
171+
* or the camera device has been closed.
172+
* @throws IllegalArgumentException if the Surface is invalid, not part of this Session, or has
173+
* already been used as a target of a CaptureRequest in this
174+
* session or immediately prior sessions.
175+
*
176+
* @hide
177+
*/
178+
public abstract void tearDown(@NonNull Surface surface) throws CameraAccessException;
179+
141180
/**
142181
* <p>Submit a request for an image to be captured by the camera device.</p>
143182
*

core/java/android/hardware/camera2/ICameraDeviceUser.aidl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,6 @@ interface ICameraDeviceUser
100100
int flush(out LongParcelable lastFrameNumber);
101101

102102
int prepare(int streamId);
103+
104+
int tearDown(int streamId);
103105
}

core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ public void prepare(Surface surface) throws CameraAccessException {
145145
mDeviceImpl.prepare(surface);
146146
}
147147

148+
@Override
149+
public void tearDown(Surface surface) throws CameraAccessException {
150+
mDeviceImpl.tearDown(surface);
151+
}
152+
148153
@Override
149154
public synchronized int capture(CaptureRequest request, CaptureCallback callback,
150155
Handler handler) throws CameraAccessException {

core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ public void prepare(Surface surface) throws CameraAccessException {
168168
mSessionImpl.prepare(surface);
169169
}
170170

171+
@Override
172+
public void tearDown(Surface surface) throws CameraAccessException {
173+
mSessionImpl.tearDown(surface);
174+
}
175+
171176
@Override
172177
public int capture(CaptureRequest request, CaptureCallback listener, Handler handler)
173178
throws CameraAccessException {

core/java/android/hardware/camera2/impl/CameraDeviceImpl.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,31 @@ public void prepare(Surface surface) throws CameraAccessException {
679679
}
680680
}
681681

682+
public void tearDown(Surface surface) throws CameraAccessException {
683+
if (surface == null) throw new IllegalArgumentException("Surface is null");
684+
685+
synchronized(mInterfaceLock) {
686+
int streamId = -1;
687+
for (int i = 0; i < mConfiguredOutputs.size(); i++) {
688+
if (surface == mConfiguredOutputs.valueAt(i).getSurface()) {
689+
streamId = mConfiguredOutputs.keyAt(i);
690+
break;
691+
}
692+
}
693+
if (streamId == -1) {
694+
throw new IllegalArgumentException("Surface is not part of this session");
695+
}
696+
try {
697+
mRemoteDevice.tearDown(streamId);
698+
} catch (CameraRuntimeException e) {
699+
throw e.asChecked();
700+
} catch (RemoteException e) {
701+
// impossible
702+
return;
703+
}
704+
}
705+
}
706+
682707
public int capture(CaptureRequest request, CaptureCallback callback, Handler handler)
683708
throws CameraAccessException {
684709
if (DEBUG) {

core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,20 @@ public int prepare(int streamId) {
636636
return CameraBinderDecorator.NO_ERROR;
637637
}
638638

639+
public int tearDown(int streamId) {
640+
if (DEBUG) {
641+
Log.d(TAG, "tearDown called.");
642+
}
643+
if (mLegacyDevice.isClosed()) {
644+
Log.e(TAG, "Cannot tear down stream, device has been closed.");
645+
return CameraBinderDecorator.ENODEV;
646+
}
647+
648+
// LEGACY doesn't support actual teardown, so just a no-op
649+
650+
return CameraBinderDecorator.NO_ERROR;
651+
}
652+
639653
@Override
640654
public IBinder asBinder() {
641655
// This is solely intended to be used for in-process binding.

0 commit comments

Comments
 (0)