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