libbufferstreams: Add a StreamConfig type (and associated trait methods)

This type will be used to create publishers and subscribers, and
contains enough information to create AHardwareBuffers.

Bug: 296100790, 296450062
Test: atest libbufferstreams-internal_test
Change-Id: I12a2aa59e8931ab77c658371d16450f3618de8ce
diff --git a/libs/bufferstreams/rust/src/lib.rs b/libs/bufferstreams/rust/src/lib.rs
index 1d321c8..7bd8e38 100644
--- a/libs/bufferstreams/rust/src/lib.rs
+++ b/libs/bufferstreams/rust/src/lib.rs
@@ -14,6 +14,10 @@
 
 //! libbufferstreams: Reactive Streams for Graphics Buffers
 
+mod stream_config;
+
+pub use stream_config::*;
+
 use nativewindow::*;
 use std::sync::{Arc, Weak};
 use std::time::Instant;
@@ -50,6 +54,8 @@
 /// *  A Publisher MAY support multiple Subscribers and decides whether each
 /// Subscription is unicast or multicast.
 pub trait BufferPublisher {
+    /// Returns the StreamConfig of buffers that publisher creates.
+    fn get_publisher_stream_config(&self) -> StreamConfig;
     /// This function will create the subscription between the publisher and
     /// the subscriber.
     fn subscribe(&self, subscriber: Weak<dyn BufferSubscriber>);
@@ -82,6 +88,8 @@
 /// *   A Publisher MAY support multiple Subscribers and decides whether each
 /// Subscription is unicast or multicast.
 pub trait BufferSubscriber {
+    /// The StreamConfig of buffers that this subscriber expects.
+    fn get_subscriber_stream_config(&self) -> StreamConfig;
     /// This function will be called at the beginning of the subscription.
     fn on_subscribe(&self, subscription: Arc<dyn BufferSubscription>);
     /// This function will be called for buffer that comes in.
diff --git a/libs/bufferstreams/rust/src/stream_config.rs b/libs/bufferstreams/rust/src/stream_config.rs
new file mode 100644
index 0000000..d0c621b
--- /dev/null
+++ b/libs/bufferstreams/rust/src/stream_config.rs
@@ -0,0 +1,67 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use nativewindow::*;
+
+/// The configuration of the buffers published by a [BufferPublisher] or
+/// expected by a [BufferSubscriber].
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct StreamConfig {
+    /// Width in pixels of streaming buffers.
+    pub width: u32,
+    /// Height in pixels of streaming buffers.
+    pub height: u32,
+    /// Number of layers of streaming buffers.
+    pub layers: u32,
+    /// Format of streaming buffers.
+    pub format: AHardwareBuffer_Format::Type,
+    /// Usage of streaming buffers.
+    pub usage: AHardwareBuffer_UsageFlags,
+    /// Stride of streaming buffers.
+    pub stride: u32,
+}
+
+impl StreamConfig {
+    /// Tries to create a new AHardwareBuffer from settings in a [StreamConfig].
+    pub fn create_hardware_buffer(&self) -> Option<AHardwareBuffer> {
+        AHardwareBuffer::new(self.width, self.height, self.layers, self.format, self.usage)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_create_hardware_buffer() {
+        let config = StreamConfig {
+            width: 123,
+            height: 456,
+            layers: 1,
+            format: AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+            usage: AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN
+                | AHardwareBuffer_UsageFlags::AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+            stride: 0,
+        };
+
+        let maybe_buffer = config.create_hardware_buffer();
+        assert!(maybe_buffer.is_some());
+
+        let buffer = maybe_buffer.unwrap();
+        assert_eq!(config.width, buffer.width());
+        assert_eq!(config.height, buffer.height());
+        assert_eq!(config.format, buffer.format());
+        assert_eq!(config.usage, buffer.usage());
+    }
+}