[media] Add test to ensure CodecImpl's BufferCollections close cleanly

Due to the addition of `EnsureBuffersNotConfigured()` in the relevant
code paths (see commit d04382d70c0), it appears that Bug 37257 was
already resolved.

Added a test to ensure this behaviour persists, and also removed some
dead code.

Bug: 37257
Test: fx run-test decryptor_adapter_tests
Change-Id: Icf2c7da4fe1c20c6b9d323c1479ec38d1face5c7
diff --git a/src/media/lib/codec_impl/codec_impl.cc b/src/media/lib/codec_impl/codec_impl.cc
index 007390c..a4ed6be 100644
--- a/src/media/lib/codec_impl/codec_impl.cc
+++ b/src/media/lib/codec_impl/codec_impl.cc
@@ -1348,15 +1348,10 @@
 
     EnsureBuffersNotConfigured(lock, kOutputPort);
 
-    // This unbinds any BufferCollection bindings.  This is effectively part
-    // of the overall unbind of anything generating activity on FIDL thread
-    // based on incoming channel messages.
-    if (port_settings_[kInputPort] && port_settings_[kInputPort]->is_partial_settings()) {
-      port_settings_[kInputPort]->UnbindBufferCollection();
-    }
-    if (port_settings_[kOutputPort] && port_settings_[kOutputPort]->is_partial_settings()) {
-      port_settings_[kOutputPort]->UnbindBufferCollection();
-    }
+    // By this point both PortSettings should have already been deleted.
+    ZX_DEBUG_ASSERT(!port_settings_[kInputPort]);
+    ZX_DEBUG_ASSERT(!port_settings_[kOutputPort]);
+
     // Unbind the sysmem_ fuchsia::sysmem::Allocator connection - this also
     // ensures that any in-flight requests' completions will not run.
     sysmem_.Unbind();
diff --git a/src/media/lib/codec_impl/unit_tests/test_decryptor_adapter.cc b/src/media/lib/codec_impl/unit_tests/test_decryptor_adapter.cc
index 2ff4c47..83009c3 100644
--- a/src/media/lib/codec_impl/unit_tests/test_decryptor_adapter.cc
+++ b/src/media/lib/codec_impl/unit_tests/test_decryptor_adapter.cc
@@ -543,6 +543,55 @@
   AssertNoChannelErrors();
 }
 
+TEST_F(ClearDecryptorAdapterTest, DecryptorClosesBuffersCleanly) {
+  ConnectDecryptor(false);
+  decryptor_adapter_->set_has_keys(true);
+
+  RunLoopUntil([this]() { return input_buffer_info_.has_value(); });
+  AssertNoChannelErrors();
+  ASSERT_TRUE(input_buffer_info_);
+
+  ConfigureInputPackets();
+
+  decryptor_->QueueInputFormatDetails(kStreamLifetimeOrdinal,
+                                      CreateInputFormatDetails("clear", {}, {}));
+
+  // Queue a single input packet.
+  ASSERT_TRUE(HasFreePackets());
+  decryptor_->QueueInputPacket(CreateInputPacket(*input_iter_++));
+
+  // Wait until the output collection has been allocated.
+  RunLoopUntil([this]() { return output_buffer_info_.has_value(); });
+  AssertNoChannelErrors();
+  ASSERT_TRUE(output_buffer_info_);
+
+  // Wait until receive first output packet.
+  RunLoopUntil([this]() { return !output_data_.empty(); });
+  AssertNoChannelErrors();
+
+  // Drop the decryptor_. This should not cause any buffer collection failures.
+  decryptor_ = nullptr;
+  AssertNoChannelErrors();
+
+  // If the below fail, the collections have failed.
+  std::optional<zx_status_t> input_status;
+  std::optional<zx_status_t> output_status;
+  EXPECT_TRUE(input_collection_.is_bound());
+  EXPECT_TRUE(output_collection_.is_bound());
+  input_collection_->CheckBuffersAllocated([&input_status](zx_status_t s) { input_status = s; });
+  output_collection_->CheckBuffersAllocated([&output_status](zx_status_t s) { output_status = s; });
+  RunLoopUntil([&]() { return input_status.has_value() && output_status.has_value(); });
+  EXPECT_EQ(*input_status, ZX_OK);
+  EXPECT_EQ(*output_status, ZX_OK);
+  AssertNoChannelErrors();
+  EXPECT_FALSE(stream_error_.has_value());
+
+  // Buffers are A-OK after dropping decryptor_.
+
+  // ClearText decryptor just copies data across, and only one input packet was sent.
+  EXPECT_EQ(output_data_[0], input_data_[0]);
+}
+
 class SecureDecryptorAdapterTest : public DecryptorAdapterTest<FakeSecureDecryptorAdapter> {};
 
 TEST_F(SecureDecryptorAdapterTest, FailsToAcquireSecureBuffers) {