From 2d99c9f930f6c438bf83e379953552c71c3ae345 Mon Sep 17 00:00:00 2001 From: Rucha Katakwar Date: Wed, 25 Aug 2021 11:39:27 -0700 Subject: Camera:Fix the memory leak caused during HFR mode. During high speed recording mode, it was observed that there was a memory leak due to too many nodes at mPendingFrameNumbersWithOtherType list. After ag/1962479 added batching for HFR it only updates the FrameNumberTracker every 4 or 8 frames during high speed recording. This change fixes that by updating every frame. A map is used to store requestIds which have batchOutput. For every such requests we update each frame in the batch in a for loop. bug: 194618660 Test: 1. Did validity check with the change. Now frameNumber is incremented by 1 instead of every 4 or 8 in FrameNumberTracker. 2. The mPendingFrameNumbersWithOtherType for otherType is empty during HFR recording. 3. Verified using other modes of camera and did not observe any crashes. 4. CTS tests Pass. Change-Id: I2638e6663e7b70e4ef7a29dfeb27d423c9c7137d (cherry picked from commit 236ed73e2663f15d89bbf0e4a2171f5595eb0143) --- .../hardware/camera2/impl/CameraDeviceImpl.java | 75 +++++++++++++++++++--- 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index fc728a22ed5a..4708f3e0664f 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -104,6 +104,9 @@ public class CameraDeviceImpl extends CameraDevice private SparseArray mCaptureCallbackMap = new SparseArray(); + /** map request IDs which have batchedOutputs to requestCount*/ + private HashMap mBatchOutputMap = new HashMap<>(); + private int mRepeatingRequestId = REQUEST_ID_NONE; // Latest repeating request list's types private int[] mRepeatingRequestTypes; @@ -973,6 +976,7 @@ public class CameraDeviceImpl extends CameraDevice mConfiguredInput = new SimpleEntry(REQUEST_ID_NONE, null); mIdle = true; mCaptureCallbackMap = new SparseArray(); + mBatchOutputMap = new HashMap<>(); mFrameNumberTracker = new FrameNumberTracker(); mCurrentSession.closeWithoutDraining(); @@ -1179,6 +1183,41 @@ public class CameraDeviceImpl extends CameraDevice return requestTypes; } + private boolean hasBatchedOutputs(List requestList) { + boolean hasBatchedOutputs = true; + for (int i = 0; i < requestList.size(); i++) { + CaptureRequest request = requestList.get(i); + if (!request.isPartOfCRequestList()) { + hasBatchedOutputs = false; + break; + } + if (i == 0) { + Collection targets = request.getTargets(); + if (targets.size() != 2) { + hasBatchedOutputs = false; + break; + } + } + } + return hasBatchedOutputs; + } + + private void updateTracker(int requestId, long frameNumber, + int requestType, CaptureResult result, boolean isPartialResult) { + int requestCount = 1; + // If the request has batchedOutputs update each frame within the batch. + if (mBatchOutputMap.containsKey(requestId)) { + requestCount = mBatchOutputMap.get(requestId); + for (int i = 0; i < requestCount; i++) { + mFrameNumberTracker.updateTracker(frameNumber - (requestCount - 1 - i), + result, isPartialResult, requestType); + } + } else { + mFrameNumberTracker.updateTracker(frameNumber, result, + isPartialResult, requestType); + } + } + private int submitCaptureRequest(List requestList, CaptureCallback callback, Executor executor, boolean repeating) throws CameraAccessException { @@ -1224,6 +1263,14 @@ public class CameraDeviceImpl extends CameraDevice request.recoverStreamIdToSurface(); } + // If the request has batched outputs, then store the + // requestCount and requestId in the map. + boolean hasBatchedOutputs = hasBatchedOutputs(requestList); + if (hasBatchedOutputs) { + int requestCount = requestList.size(); + mBatchOutputMap.put(requestInfo.getRequestId(), requestCount); + } + if (callback != null) { mCaptureCallbackMap.put(requestInfo.getRequestId(), new CaptureCallbackHolder( @@ -1839,8 +1886,18 @@ public class CameraDeviceImpl extends CameraDevice if (DEBUG) { Log.v(TAG, String.format("got error frame %d", frameNumber)); } - mFrameNumberTracker.updateTracker(frameNumber, - /*error*/true, request.getRequestType()); + + // Update FrameNumberTracker for every frame during HFR mode. + if (mBatchOutputMap.containsKey(requestId)) { + for (int i = 0; i < mBatchOutputMap.get(requestId); i++) { + mFrameNumberTracker.updateTracker(frameNumber - (subsequenceId - i), + /*error*/true, request.getRequestType()); + } + } else { + mFrameNumberTracker.updateTracker(frameNumber, + /*error*/true, request.getRequestType()); + } + checkAndFireSequenceComplete(); // Dispatch the failure callback @@ -2023,7 +2080,6 @@ public class CameraDeviceImpl extends CameraDevice public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras, PhysicalCaptureResultInfo physicalResults[]) throws RemoteException { - int requestId = resultExtras.getRequestId(); long frameNumber = resultExtras.getFrameNumber(); @@ -2064,8 +2120,8 @@ public class CameraDeviceImpl extends CameraDevice + frameNumber); } - mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, /*result*/null, + isPartialResult); return; } @@ -2077,8 +2133,9 @@ public class CameraDeviceImpl extends CameraDevice + frameNumber); } - mFrameNumberTracker.updateTracker(frameNumber, /*result*/null, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, /*result*/null, + isPartialResult); + return; } @@ -2184,9 +2241,7 @@ public class CameraDeviceImpl extends CameraDevice Binder.restoreCallingIdentity(ident); } - // Collect the partials for a total result; or mark the frame as totally completed - mFrameNumberTracker.updateTracker(frameNumber, finalResult, isPartialResult, - requestType); + updateTracker(requestId, frameNumber, requestType, finalResult, isPartialResult); // Fire onCaptureSequenceCompleted if (!isPartialResult) { -- cgit v1.2.3-59-g8ed1b