diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 1e2cbeeb92d1..ecdc0922e90b 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -1282,6 +1282,17 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
 		return -EINVAL;
 	}
 
+	/*
+	 * Once the CameraConfiguration has been adjusted/validated
+	 * it can be applied to the camera.
+	 */
+	int ret = camera_->configure(config_.get());
+	if (ret) {
+		LOG(HAL, Error) << "Failed to configure camera '"
+				<< camera_->id() << "'";
+		return ret;
+	}
+
 	/*
 	 * Configure the HAL CameraStream instances using the associated
 	 * StreamConfiguration and set the number of required buffers in
@@ -1295,17 +1306,6 @@ int CameraDevice::configureStreams(camera3_stream_configuration_t *stream_list)
 		}
 	}
 
-	/*
-	 * Once the CameraConfiguration has been adjusted/validated
-	 * it can be applied to the camera.
-	 */
-	int ret = camera_->configure(config_.get());
-	if (ret) {
-		LOG(HAL, Error) << "Failed to configure camera '"
-				<< camera_->id() << "'";
-		return ret;
-	}
-
 	return 0;
 }
 
diff --git a/src/android/camera_stream.cpp b/src/android/camera_stream.cpp
index f899be4fe007..eac1480530f8 100644
--- a/src/android/camera_stream.cpp
+++ b/src/android/camera_stream.cpp
@@ -26,6 +26,11 @@ CameraStream::CameraStream(CameraDevice *cameraDevice, Type type,
 
 	if (type_ == Type::Internal || type_ == Type::Mapped)
 		encoder_ = std::make_unique<EncoderLibJpeg>();
+
+	if (type == Type::Internal) {
+		allocator_ = std::make_unique<FrameBufferAllocator>(cameraDevice_->camera());
+		mutex_ = std::make_unique<std::mutex>();
+	}
 }
 
 const StreamConfiguration &CameraStream::configuration() const
@@ -46,6 +51,16 @@ int CameraStream::configure()
 			return ret;
 	}
 
+	if (allocator_) {
+		int ret = allocator_->allocate(stream());
+		if (ret < 0)
+			return ret;
+
+		/* Save a pointer to the reserved frame buffers */
+		for (const auto &frameBuffer : allocator_->buffers(stream()))
+			buffers_.push_back(frameBuffer.get());
+	}
+
 	camera3Stream_->max_buffers = configuration().bufferCount;
 
 	return 0;
@@ -109,3 +124,31 @@ int CameraStream::process(const libcamera::FrameBuffer &source,
 
 	return 0;
 }
+
+FrameBuffer *CameraStream::getBuffer()
+{
+	if (!allocator_)
+		return nullptr;
+
+	std::lock_guard<std::mutex> locker(*mutex_);
+
+	if (buffers_.empty()) {
+		LOG(HAL, Error) << "Buffer underrun";
+		return nullptr;
+	}
+
+	FrameBuffer *buffer = buffers_.back();
+	buffers_.pop_back();
+
+	return buffer;
+}
+
+void CameraStream::putBuffer(libcamera::FrameBuffer *buffer)
+{
+	if (!allocator_)
+		return;
+
+	std::lock_guard<std::mutex> locker(*mutex_);
+
+	buffers_.push_back(buffer);
+}
diff --git a/src/android/camera_stream.h b/src/android/camera_stream.h
index 4c51f0fb3393..f929e8260ae3 100644
--- a/src/android/camera_stream.h
+++ b/src/android/camera_stream.h
@@ -8,11 +8,14 @@
 #define __ANDROID_CAMERA_STREAM_H__
 
 #include <memory>
+#include <mutex>
+#include <vector>
 
 #include <hardware/camera3.h>
 
 #include <libcamera/buffer.h>
 #include <libcamera/camera.h>
+#include <libcamera/framebuffer_allocator.h>
 #include <libcamera/geometry.h>
 #include <libcamera/pixel_format.h>
 
@@ -117,6 +120,8 @@ public:
 	int configure();
 	int process(const libcamera::FrameBuffer &source,
 		    MappedCamera3Buffer *dest, CameraMetadata *metadata);
+	libcamera::FrameBuffer *getBuffer();
+	void putBuffer(libcamera::FrameBuffer *buffer);
 
 private:
 	CameraDevice *cameraDevice_;
@@ -129,7 +134,11 @@ private:
 	 * one or more streams to the Android framework.
 	 */
 	unsigned int index_;
+
 	std::unique_ptr<Encoder> encoder_;
+	std::unique_ptr<libcamera::FrameBufferAllocator> allocator_;
+	std::vector<libcamera::FrameBuffer *> buffers_;
+	std::unique_ptr<std::mutex> mutex_;
 };
 
 #endif /* __ANDROID_CAMERA_STREAM__ */
