Camera: prevent requestStreamBuffers break IDLE state
Test: CTS
Bug: 109829698
Change-Id: Ib9092e4e6b7d6cee2fbd96a3209e3b760f9fdaf0
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 5c0f570..4f5be6b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1249,12 +1249,81 @@
// b/79972865
Mutex mTrackerLock;
- // Whether HAL request buffers through requestStreamBuffer API
+ // Whether HAL request buffers through requestStreamBuffers API
bool mUseHalBufManager = false;
// Lock to ensure requestStreamBuffers() callbacks are serialized
std::mutex mRequestBufferInterfaceLock;
+ // The state machine to control when requestStreamBuffers should allow
+ // HAL to request buffers.
+ enum RequestBufferState {
+ /**
+ * This is the initial state.
+ * requestStreamBuffers call will return FAILED_CONFIGURING in this state.
+ * Will switch to RB_STATUS_READY after a successful configureStreams or
+ * processCaptureRequest call.
+ */
+ RB_STATUS_STOPPED,
+
+ /**
+ * requestStreamBuffers call will proceed in this state.
+ * When device is asked to stay idle via waitUntilStateThenRelock() call:
+ * - Switch to RB_STATUS_STOPPED if there is no inflight requests and
+ * request thread is paused.
+ * - Switch to RB_STATUS_PENDING_STOP otherwise
+ */
+ RB_STATUS_READY,
+
+ /**
+ * requestStreamBuffers call will proceed in this state.
+ * Switch to RB_STATUS_STOPPED when all inflight requests are fulfilled
+ * and request thread is paused
+ */
+ RB_STATUS_PENDING_STOP,
+ };
+
+ class RequestBufferStateMachine {
+ public:
+ status_t initialize(sp<camera3::StatusTracker> statusTracker);
+
+ // Return if the state machine currently allows for requestBuffers
+ // If the state allows for it, mRequestBufferOngoing will be set to true
+ // and caller must call endRequestBuffer() later to unset the flag
+ bool startRequestBuffer();
+ void endRequestBuffer();
+
+ // Events triggered by application API call
+ void onStreamsConfigured();
+ void onWaitUntilIdle();
+
+ // Events usually triggered by hwBinder processCaptureResult callback thread
+ // But can also be triggered on request thread for failed request, or on
+ // hwbinder notify callback thread for shutter/error callbacks
+ void onInflightMapEmpty();
+
+ // Events triggered by RequestThread
+ void onRequestSubmitted();
+ void onRequestThreadPaused();
+
+ private:
+ void notifyTrackerLocked(bool active);
+
+ // Switch to STOPPED state and return true if all conditions allows for it.
+ // Otherwise do nothing and return false.
+ bool checkSwitchToStopLocked();
+
+ std::mutex mLock;
+ RequestBufferState mStatus = RB_STATUS_STOPPED;
+
+ bool mRequestThreadPaused = true;
+ bool mInflightMapEmpty = true;
+ bool mRequestBufferOngoing = false;
+
+ wp<camera3::StatusTracker> mStatusTracker;
+ int mRequestBufferStatusId;
+ } mRequestBufferSM;
+
}; // class Camera3Device
}; // namespace android