diff --git a/repos/os/recipes/pkg/black_hole/README b/repos/os/recipes/pkg/black_hole/README
new file mode 100644
index 0000000000..3c837fc190
--- /dev/null
+++ b/repos/os/recipes/pkg/black_hole/README
@@ -0,0 +1,2 @@
+
+ Runtime for deploying the black hole component from the depot
diff --git a/repos/os/recipes/pkg/black_hole/archives b/repos/os/recipes/pkg/black_hole/archives
new file mode 100644
index 0000000000..e331bb0e35
--- /dev/null
+++ b/repos/os/recipes/pkg/black_hole/archives
@@ -0,0 +1 @@
+_/src/black_hole
diff --git a/repos/os/recipes/pkg/black_hole/hash b/repos/os/recipes/pkg/black_hole/hash
new file mode 100644
index 0000000000..009aeec759
--- /dev/null
+++ b/repos/os/recipes/pkg/black_hole/hash
@@ -0,0 +1 @@
+2021-08-24 3200fb247859dffd0825d7ed21be65932cc6c752
diff --git a/repos/os/recipes/pkg/black_hole/runtime b/repos/os/recipes/pkg/black_hole/runtime
new file mode 100644
index 0000000000..813a43eb41
--- /dev/null
+++ b/repos/os/recipes/pkg/black_hole/runtime
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/repos/os/recipes/src/black_hole/content.mk b/repos/os/recipes/src/black_hole/content.mk
new file mode 100644
index 0000000000..a0cef1ba23
--- /dev/null
+++ b/repos/os/recipes/src/black_hole/content.mk
@@ -0,0 +1,2 @@
+SRC_DIR = src/server/black_hole
+include $(GENODE_DIR)/repos/base/recipes/src/content.inc
diff --git a/repos/os/recipes/src/black_hole/hash b/repos/os/recipes/src/black_hole/hash
new file mode 100644
index 0000000000..77c3556475
--- /dev/null
+++ b/repos/os/recipes/src/black_hole/hash
@@ -0,0 +1 @@
+2021-08-24 0dd5287293a6c95313cd5f82c56a14e174e8bf35
diff --git a/repos/os/recipes/src/black_hole/used_apis b/repos/os/recipes/src/black_hole/used_apis
new file mode 100644
index 0000000000..56a415c335
--- /dev/null
+++ b/repos/os/recipes/src/black_hole/used_apis
@@ -0,0 +1,2 @@
+base
+audio_out_session
diff --git a/repos/os/src/server/black_hole/README b/repos/os/src/server/black_hole/README
new file mode 100644
index 0000000000..4eff4fc987
--- /dev/null
+++ b/repos/os/src/server/black_hole/README
@@ -0,0 +1,9 @@
+The 'black_hole' component provides dummy implementations of common
+session interfaces.
+
+At this time, only the 'Audio_out' session is provided if enabled
+in the configuration of the component:
+
+
+
+
diff --git a/repos/os/src/server/black_hole/audio_out.h b/repos/os/src/server/black_hole/audio_out.h
new file mode 100644
index 0000000000..0c105987cd
--- /dev/null
+++ b/repos/os/src/server/black_hole/audio_out.h
@@ -0,0 +1,162 @@
+/*
+ * \brief 'Audio_out' part of black hole component
+ * \author Christian Prochaska
+ * \date 2021-07-07
+ *
+ */
+
+/*
+ * Copyright (C) 2021 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _AUDIO_OUT_H_
+#define _AUDIO_OUT_H_
+
+/* Genode includes */
+#include
+#include
+
+
+namespace Audio_out
+{
+ class Session_component_base;
+ class Session_component;
+ class Root;
+}
+
+
+/**
+ * This base struct is needed to get the 'Signal_handler' constructed
+ * before the 'Session_rpc_object' constructor is called with the handler
+ * as argument.
+ */
+
+struct Audio_out::Session_component_base
+{
+ Genode::Signal_handler _data_available_handler;
+ Timer::One_shot_timeout _timeout;
+
+ virtual void _handle_data_available() = 0;
+ virtual void _handle_timeout(Genode::Duration) = 0;
+
+ Session_component_base(Genode::Env &env, Timer::Connection &timer)
+ : _data_available_handler(env.ep(),
+ *this,
+ &Session_component_base::_handle_data_available),
+ _timeout(timer, *this, &Session_component_base::_handle_timeout)
+ { }
+
+ virtual ~Session_component_base() { }
+};
+
+
+class Audio_out::Session_component : Audio_out::Session_component_base,
+ public Audio_out::Session_rpc_object
+{
+ private:
+
+ /* subtract 200ms for overhead */
+ Genode::Microseconds _delay {
+ ((Audio_out::PERIOD * 1000 * 1000) / Audio_out::SAMPLE_RATE) - 200 };
+
+ void _handle_data_available() override
+ {
+ _timeout.schedule(_delay);
+ }
+
+ void _handle_timeout(Genode::Duration) override
+ {
+ if (stream()->empty())
+ return;
+
+ bool const full = stream()->full();
+
+ Packet *p = stream()->get(stream()->pos());
+ p->invalidate();
+ p->mark_as_played();
+ stream()->increment_position();
+ progress_submit();
+
+ if (full) alloc_submit();
+
+ if (!stream()->empty())
+ _timeout.schedule(_delay);
+ }
+
+ public:
+
+ Session_component(Genode::Env &env, Timer::Connection &timer)
+ : Session_component_base(env, timer),
+ Session_rpc_object(env, _data_available_handler)
+ { }
+
+ ~Session_component()
+ {
+ if (Session_rpc_object::active()) stop();
+ }
+
+ void start() override
+ {
+ Session_rpc_object::start();
+ stream()->pos(0);
+ }
+
+ void stop() override
+ {
+ Session_rpc_object::stop();
+ }
+};
+
+
+namespace Audio_out {
+ typedef Genode::Root_component Root_component;
+}
+
+
+class Audio_out::Root : public Audio_out::Root_component
+{
+ private:
+
+ Genode::Env &_env;
+ Timer::Connection _timer;
+
+ Session_component *_create_session(const char *args) override
+ {
+ using namespace Genode;
+
+ size_t ram_quota =
+ Arg_string::find_arg(args, "ram_quota").ulong_value(0);
+
+ size_t session_size = align_addr(sizeof(Session_component), 12);
+
+ if ((ram_quota < session_size) ||
+ (sizeof(Stream) > ram_quota - session_size)) {
+ Genode::error("insufficient 'ram_quota', got ", ram_quota, ", "
+ "need ", sizeof(Stream) + session_size);
+ throw Insufficient_ram_quota();
+ }
+
+ Session_component *session = new (md_alloc())
+ Session_component(_env, _timer);
+
+ return session;
+
+ }
+
+ void _destroy_session(Session_component *session) override
+ {
+ Genode::destroy(md_alloc(), session);
+ }
+
+ public:
+
+ Root(Genode::Env &env,
+ Genode::Allocator &md_alloc)
+ : Root_component(env.ep(), md_alloc),
+ _env(env), _timer(env) { }
+};
+
+#endif /* _AUDIO_OUT_H_ */
diff --git a/repos/os/src/server/black_hole/main.cc b/repos/os/src/server/black_hole/main.cc
new file mode 100644
index 0000000000..0a33c5b442
--- /dev/null
+++ b/repos/os/src/server/black_hole/main.cc
@@ -0,0 +1,54 @@
+/*
+ * \brief Black hole component
+ * \author Christian Prochaska
+ * \date 2021-07-07
+ *
+ */
+
+/*
+ * Copyright (C) 2021 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* local includes */
+#include "audio_out.h"
+
+
+/***************
+ ** Component **
+ ***************/
+
+namespace Black_hole { struct Main; }
+
+struct Black_hole::Main
+{
+ Genode::Env &env;
+
+ Genode::Sliced_heap heap { env.ram(), env.rm() };
+
+ Genode::Constructible audio_out_root { };
+
+ Main(Genode::Env &env) : env(env)
+ {
+ Genode::Attached_rom_dataspace _config_rom { env, "config" };
+
+ if (_config_rom.xml().has_sub_node("audio_out")) {
+ audio_out_root.construct(env, heap);
+ env.parent().announce(env.ep().manage(*audio_out_root));
+ }
+ }
+};
+
+
+void Component::construct(Genode::Env &env)
+{ static Black_hole::Main inst(env); }
diff --git a/repos/os/src/server/black_hole/target.mk b/repos/os/src/server/black_hole/target.mk
new file mode 100644
index 0000000000..a79e1e4981
--- /dev/null
+++ b/repos/os/src/server/black_hole/target.mk
@@ -0,0 +1,3 @@
+TARGET = black_hole
+SRC_CC = main.cc
+LIBS = base