drm_hwcomposer: Add hwc3 frontend stub

Adds a stub implementation of the HWC3 interface and service.
This is a barebones implementation of HWC3 interface that should contain
all the necessary code to build a HWC3 module but provides no
functionality.

The project [1] was used as a reference.
[1]: https://android.googlesource.com/platform/hardware/google/graphics/common/+/refs/tags/android-13.0.0_r18/hwc3/

Change-Id: I99754bb72f12183a94b24b7182cb7857173b31d2
Co-authored-by: Roman Stratiienko <r.stratiienko@gmail.com>
Signed-off-by: Dennis Tsiang <dennis.tsiang@arm.com>
Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
Signed-off-by: Normunds Rieksts <normunds.rieksts@arm.com>
Signed-off-by: Drew Davenport <ddavenport@google.com>
diff --git a/hwc3/Composer.cpp b/hwc3/Composer.cpp
new file mode 100644
index 0000000..5f90797
--- /dev/null
+++ b/hwc3/Composer.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include "Composer.h"
+
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+
+#include "utils/log.h"
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+// NOLINTNEXTLINE
+#define DEBUG_FUNC() ALOGV("%s", __func__)
+
+ndk::ScopedAStatus Composer::createClient(
+    std::shared_ptr<IComposerClient>* out_client) {
+  DEBUG_FUNC();
+
+  auto client = ndk::SharedRefBase::make<ComposerClient>();
+  if (!client) {
+    *out_client = nullptr;
+    return ndk::ScopedAStatus::fromServiceSpecificError(EX_NO_RESOURCES);
+  }
+
+  *out_client = client;
+
+  return ndk::ScopedAStatus::ok();
+}
+
+binder_status_t Composer::dump(int fd, const char** /*args*/,
+                               uint32_t /*numArgs*/) {
+  auto output = std::string("hwc3-drm");
+  write(fd, output.c_str(), output.size());
+  return STATUS_OK;
+}
+
+ndk::ScopedAStatus Composer::getCapabilities(
+    std::vector<Capability>* /*caps*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+::ndk::SpAIBinder Composer::createBinder() {
+  auto binder = BnComposer::createBinder();
+  AIBinder_setInheritRt(binder.get(), true);
+  return binder;
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/Composer.h b/hwc3/Composer.h
new file mode 100644
index 0000000..b29d0cf
--- /dev/null
+++ b/hwc3/Composer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/graphics/composer3/BnComposer.h>
+#include <utils/Mutex.h>
+
+#include "ComposerClient.h"
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+class Composer : public BnComposer {
+ public:
+  Composer() = default;
+
+  binder_status_t dump(int fd, const char** args, uint32_t num_args) override;
+
+  // compser3 api
+  ndk::ScopedAStatus createClient(
+      std::shared_ptr<IComposerClient>* client) override;
+  ndk::ScopedAStatus getCapabilities(std::vector<Capability>* caps) override;
+
+ protected:
+  ::ndk::SpAIBinder createBinder() override;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp
new file mode 100644
index 0000000..9ebba31
--- /dev/null
+++ b/hwc3/ComposerClient.cpp
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include "ComposerClient.h"
+
+#include <android-base/logging.h>
+#include <android/binder_ibinder_platform.h>
+
+#include "utils/log.h"
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+// NOLINTNEXTLINE
+#define DEBUG_FUNC() ALOGV("%s", __func__)
+
+ComposerClient::~ComposerClient() {
+  DEBUG_FUNC();
+
+  LOG(DEBUG) << "removed composer client";
+}
+
+// no need to check nullptr for output parameter, the aidl stub code won't pass
+// nullptr
+ndk::ScopedAStatus ComposerClient::createLayer(int64_t /*display*/,
+                                               int32_t /*bufferSlotCount*/,
+                                               int64_t* /*layer*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::createVirtualDisplay(
+    int32_t /*width*/, int32_t /*height*/, AidlPixelFormat /*formatHint*/,
+    int32_t /*outputBufferSlotCount*/, VirtualDisplay* /*display*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t /*display*/,
+                                                int64_t /*layer*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t /*display*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::executeCommands(
+    const std::vector<DisplayCommand>& /*commands*/,
+    std::vector<CommandResultPayload>* /*results*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getActiveConfig(int64_t /*display*/,
+                                                   int32_t* /*config*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getColorModes(
+    int64_t /*display*/, std::vector<ColorMode>* /*colorModes*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDataspaceSaturationMatrix(
+    common::Dataspace /*dataspace*/, std::vector<float>* /*matrix*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayAttribute(
+    int64_t /*display*/, int32_t /*config*/, DisplayAttribute /*attribute*/,
+    int32_t* /*value*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayCapabilities(
+    int64_t /*display*/, std::vector<DisplayCapability>* /*caps*/) {
+  DEBUG_FUNC();
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayConfigs(
+    int64_t /*display*/, std::vector<int32_t>* /*configs*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayConnectionType(
+    int64_t /*display*/, DisplayConnectionType* /*type*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayIdentificationData(
+    int64_t /*display*/, DisplayIdentification* /*id*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayName(int64_t /*display*/,
+                                                  std::string* /*name*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayVsyncPeriod(
+    int64_t /*display*/, int32_t* /*vsyncPeriod*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayedContentSample(
+    int64_t /*display*/, int64_t /*maxFrames*/, int64_t /*timestamp*/,
+    DisplayContentSample* /*samples*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayedContentSamplingAttributes(
+    int64_t /*display*/, DisplayContentSamplingAttributes* /*attrs*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayPhysicalOrientation(
+    int64_t /*display*/, common::Transform* /*orientation*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getHdrCapabilities(
+    int64_t /*display*/, HdrCapabilities* /*caps*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getMaxVirtualDisplayCount(
+    int32_t* /*count*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getPerFrameMetadataKeys(
+    int64_t /*display*/, std::vector<PerFrameMetadataKey>* /*keys*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getReadbackBufferAttributes(
+    int64_t /*display*/, ReadbackBufferAttributes* /*attrs*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getReadbackBufferFence(
+    int64_t /*display*/, ndk::ScopedFileDescriptor* /*acquireFence*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getRenderIntents(
+    int64_t /*display*/, ColorMode /*mode*/,
+    std::vector<RenderIntent>* /*intents*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getSupportedContentTypes(
+    int64_t /*display*/, std::vector<ContentType>* /*types*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getDisplayDecorationSupport(
+    int64_t /*display*/,
+    std::optional<common::DisplayDecorationSupport>* /*supportStruct*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::registerCallback(
+    const std::shared_ptr<IComposerCallback>& /*callback*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setActiveConfig(int64_t /*display*/,
+                                                   int32_t /*config*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setActiveConfigWithConstraints(
+    int64_t /*display*/, int32_t /*config*/,
+    const VsyncPeriodChangeConstraints& /*constraints*/,
+    VsyncPeriodChangeTimeline* /*timeline*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setBootDisplayConfig(int64_t /*display*/,
+                                                        int32_t /*config*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::clearBootDisplayConfig(int64_t /*display*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::getPreferredBootDisplayConfig(
+    int64_t /*display*/, int32_t* /*config*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setAutoLowLatencyMode(int64_t /*display*/,
+                                                         bool /*on*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setClientTargetSlotCount(int64_t /*display*/,
+                                                            int32_t /*count*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setColorMode(int64_t /*display*/,
+                                                ColorMode /*mode*/,
+                                                RenderIntent /*intent*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setContentType(int64_t /*display*/,
+                                                  ContentType /*type*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setDisplayedContentSamplingEnabled(
+    int64_t /*display*/, bool /*enable*/,
+    FormatColorComponent /*componentMask*/, int64_t /*maxFrames*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t /*display*/,
+                                                PowerMode /*mode*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setReadbackBuffer(
+    int64_t /*display*/, const AidlNativeHandle& /*aidlBuffer*/,
+    const ndk::ScopedFileDescriptor& /*releaseFence*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setVsyncEnabled(int64_t /*display*/,
+                                                   bool /*enabled*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ComposerClient::setIdleTimerEnabled(int64_t /*display*/,
+                                                       int32_t /*timeout*/) {
+  DEBUG_FUNC();
+  return ndk::ScopedAStatus::ok();
+}
+
+::ndk::SpAIBinder ComposerClient::createBinder() {
+  auto binder = BnComposerClient::createBinder();
+  AIBinder_setInheritRt(binder.get(), true);
+  return binder;
+}
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/ComposerClient.h b/hwc3/ComposerClient.h
new file mode 100644
index 0000000..bdf4b0a
--- /dev/null
+++ b/hwc3/ComposerClient.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
+#include <aidl/android/hardware/graphics/composer3/BnComposerClient.h>
+#include <utils/Mutex.h>
+
+#include <memory>
+
+using AidlPixelFormat = aidl::android::hardware::graphics::common::PixelFormat;
+using AidlNativeHandle = aidl::android::hardware::common::NativeHandle;
+
+namespace aidl::android::hardware::graphics::composer3::impl {
+
+class ComposerClient : public BnComposerClient {
+ public:
+  ComposerClient() = default;
+  ~ComposerClient() override;
+
+  // composer3 interface
+  ndk::ScopedAStatus createLayer(int64_t display, int32_t buffer_slot_count,
+                                 int64_t* layer) override;
+  ndk::ScopedAStatus createVirtualDisplay(int32_t width, int32_t height,
+                                          AidlPixelFormat format_hint,
+                                          int32_t output_buffer_slot_count,
+                                          VirtualDisplay* display) override;
+  ndk::ScopedAStatus destroyLayer(int64_t display, int64_t layer) override;
+  ndk::ScopedAStatus destroyVirtualDisplay(int64_t display) override;
+  ndk::ScopedAStatus executeCommands(
+      const std::vector<DisplayCommand>& commands,
+      std::vector<CommandResultPayload>* results) override;
+  ndk::ScopedAStatus getActiveConfig(int64_t display, int32_t* config) override;
+  ndk::ScopedAStatus getColorModes(
+      int64_t display, std::vector<ColorMode>* color_modes) override;
+  ndk::ScopedAStatus getDataspaceSaturationMatrix(
+      common::Dataspace dataspace, std::vector<float>* matrix) override;
+  ndk::ScopedAStatus getDisplayAttribute(int64_t display, int32_t config,
+                                         DisplayAttribute attribute,
+                                         int32_t* value) override;
+  ndk::ScopedAStatus getDisplayCapabilities(
+      int64_t display, std::vector<DisplayCapability>* caps) override;
+  ndk::ScopedAStatus getDisplayConfigs(int64_t display,
+                                       std::vector<int32_t>* configs) override;
+  ndk::ScopedAStatus getDisplayConnectionType(
+      int64_t display, DisplayConnectionType* type) override;
+  ndk::ScopedAStatus getDisplayIdentificationData(
+      int64_t display, DisplayIdentification* id) override;
+  ndk::ScopedAStatus getDisplayName(int64_t display,
+                                    std::string* name) override;
+  ndk::ScopedAStatus getDisplayVsyncPeriod(int64_t display,
+                                           int32_t* vsync_period) override;
+  ndk::ScopedAStatus getDisplayedContentSample(
+      int64_t display, int64_t max_frames, int64_t timestamp,
+      DisplayContentSample* samples) override;
+  ndk::ScopedAStatus getDisplayedContentSamplingAttributes(
+      int64_t display, DisplayContentSamplingAttributes* attrs) override;
+  ndk::ScopedAStatus getDisplayPhysicalOrientation(
+      int64_t display, common::Transform* orientation) override;
+  ndk::ScopedAStatus getHdrCapabilities(int64_t display,
+                                        HdrCapabilities* caps) override;
+  ndk::ScopedAStatus getMaxVirtualDisplayCount(int32_t* count) override;
+  ndk::ScopedAStatus getPerFrameMetadataKeys(
+      int64_t display, std::vector<PerFrameMetadataKey>* keys) override;
+  ndk::ScopedAStatus getReadbackBufferAttributes(
+      int64_t display, ReadbackBufferAttributes* attrs) override;
+  ndk::ScopedAStatus getReadbackBufferFence(
+      int64_t display, ndk::ScopedFileDescriptor* acquire_fence) override;
+  ndk::ScopedAStatus getRenderIntents(
+      int64_t display, ColorMode mode,
+      std::vector<RenderIntent>* intents) override;
+  ndk::ScopedAStatus getSupportedContentTypes(
+      int64_t display, std::vector<ContentType>* types) override;
+  ndk::ScopedAStatus getDisplayDecorationSupport(
+      int64_t display,
+      std::optional<common::DisplayDecorationSupport>* support) override;
+  ndk::ScopedAStatus registerCallback(
+      const std::shared_ptr<IComposerCallback>& callback) override;
+  ndk::ScopedAStatus setActiveConfig(int64_t display, int32_t config) override;
+  ndk::ScopedAStatus setActiveConfigWithConstraints(
+      int64_t display, int32_t config,
+      const VsyncPeriodChangeConstraints& constraints,
+      VsyncPeriodChangeTimeline* timeline) override;
+  ndk::ScopedAStatus setBootDisplayConfig(int64_t display,
+                                          int32_t config) override;
+  ndk::ScopedAStatus clearBootDisplayConfig(int64_t display) override;
+  ndk::ScopedAStatus getPreferredBootDisplayConfig(int64_t display,
+                                                   int32_t* config) override;
+  ndk::ScopedAStatus setAutoLowLatencyMode(int64_t display, bool on) override;
+  ndk::ScopedAStatus setClientTargetSlotCount(int64_t display,
+                                              int32_t count) override;
+  ndk::ScopedAStatus setColorMode(int64_t display, ColorMode mode,
+                                  RenderIntent intent) override;
+  ndk::ScopedAStatus setContentType(int64_t display, ContentType type) override;
+  ndk::ScopedAStatus setDisplayedContentSamplingEnabled(
+      int64_t display, bool enable, FormatColorComponent component_mask,
+      int64_t max_frames) override;
+  ndk::ScopedAStatus setPowerMode(int64_t display, PowerMode mode) override;
+  ndk::ScopedAStatus setReadbackBuffer(
+      int64_t display, const AidlNativeHandle& buffer,
+      const ndk::ScopedFileDescriptor& release_fence) override;
+  ndk::ScopedAStatus setVsyncEnabled(int64_t display, bool enabled) override;
+  ndk::ScopedAStatus setIdleTimerEnabled(int64_t display,
+                                         int32_t timeout) override;
+
+ protected:
+  ::ndk::SpAIBinder createBinder() override;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3::impl
diff --git a/hwc3/hwc3-drm.rc b/hwc3/hwc3-drm.rc
new file mode 100644
index 0000000..a634b0b
--- /dev/null
+++ b/hwc3/hwc3-drm.rc
@@ -0,0 +1,7 @@
+service vendor.hwcomposer-3 /vendor/bin/hw/android.hardware.graphics.composer3-service
+    class hal animation
+    user system
+    group graphics drmrpc
+    capabilities SYS_NICE
+    onrestart restart surfaceflinger
+    task_profiles ServiceCapacityLow
diff --git a/hwc3/hwc3-drm.xml b/hwc3/hwc3-drm.xml
new file mode 100644
index 0000000..05a7c09
--- /dev/null
+++ b/hwc3/hwc3-drm.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.graphics.composer3</name>
+        <version>1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/hwc3/meson.build b/hwc3/meson.build
new file mode 100644
index 0000000..f91ea3c
--- /dev/null
+++ b/hwc3/meson.build
@@ -0,0 +1,31 @@
+
+src_hwc3 = files(
+    'ComposerClient.cpp',
+    'Composer.cpp',
+    'service.cpp',
+)
+
+executable(
+    'android.hardware.composer.hwc3-service.drm',
+    src_hwc3,
+    cpp_args : common_cpp_flags,
+    dependencies : deps,
+    install : true,
+    link_with: drmhwc_common,
+    install_dir : get_option('bindir') / 'hw',
+    include_directories: inc_include,
+)
+
+configure_file(
+  input: 'hwc3-drm.rc',
+  output: '@PLAINNAME@',
+  copy: true,
+  install_dir: get_option('sysconfdir') / 'init',
+)
+
+configure_file(
+  input: 'hwc3-drm.xml',
+  output: '@PLAINNAME@',
+  copy: true,
+  install_dir: get_option('sysconfdir') / 'vintf' / 'manifest',
+)
diff --git a/hwc3/service.cpp b/hwc3/service.cpp
new file mode 100644
index 0000000..f7527b7
--- /dev/null
+++ b/hwc3/service.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021-2022, 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.
+ */
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/ProcessState.h>
+#include <sched.h>
+
+#include "Composer.h"
+#include "utils/log.h"
+
+using aidl::android::hardware::graphics::composer3::impl::Composer;
+
+int main(int /*argc*/, char* argv[]) {
+  (void)argv;
+  ALOGI("hwc3-drm starting up");
+
+  // same as SF main thread
+  struct sched_param param = {0};
+  param.sched_priority = 2;
+  if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+    ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+  }
+
+  auto composer = ndk::SharedRefBase::make<Composer>();
+  if (!composer) {
+    ALOGE("Failed to create composer");
+    return -ENOMEM;
+  }
+
+  const std::string instance = std::string() + Composer::descriptor +
+                               "/default";
+  ALOGI("HWC3 service name %s", instance.c_str());
+  auto status = AServiceManager_addServiceWithFlags(
+      composer->asBinder().get(), instance.c_str(),
+      AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
+  if (status != STATUS_OK) {
+    ALOGE("Failed to register service. Error %d", (int)status);
+    return -EINVAL;
+  }
+
+  ABinderProcess_joinThreadPool();
+  return EXIT_FAILURE;  // should not reach
+}