Add AudioProxy HAL IDevicesFactory and IDevice Implementation

The DevicesFactory creates a default DeviceImpl instance, which forwards
openOutputStream() calls to the registered bus device.

The DeviceImpl supports multiple registered bus devices.

Bug: 152919242
Test: Tested on Android TV Device
Change-Id: I61dff6467ed22f293ae227cba39ef5e13eb3925b
diff --git a/audio_proxy/service/Android.bp b/audio_proxy/service/Android.bp
index 8697f8a..fa2bfb6 100644
--- a/audio_proxy/service/Android.bp
+++ b/audio_proxy/service/Android.bp
@@ -1,4 +1,16 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
+// Copyright (C) 2020 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.
 
 cc_binary {
   name: "device.google.atv.audio_proxy@5.0-service",
@@ -7,6 +19,9 @@
 
   srcs: [
     "AudioProxyDevicesManagerImpl.cpp",
+    "BusDeviceProvider.cpp",
+    "DeviceImpl.cpp",
+    "DevicesFactoryImpl.cpp",
     "main.cpp",
   ],
 
diff --git a/audio_proxy/service/AudioProxyDevicesManagerImpl.cpp b/audio_proxy/service/AudioProxyDevicesManagerImpl.cpp
index df64ab3..7302eec 100644
--- a/audio_proxy/service/AudioProxyDevicesManagerImpl.cpp
+++ b/audio_proxy/service/AudioProxyDevicesManagerImpl.cpp
@@ -1,7 +1,24 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
+// Copyright (C) 2020 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 "AudioProxyDevicesManagerImpl.h"
 
+#include <utils/Log.h>
+
+using ::android::OK;
+using ::android::status_t;
+
 namespace audio_proxy {
 namespace service {
 
@@ -10,7 +27,38 @@
 
 Return<bool> AudioProxyDevicesManagerImpl::registerDevice(
     const hidl_string& address, const sp<IBusDevice>& device) {
-  return false;
+  if (address.empty() || !device) {
+    return false;
+  }
+
+  if (!mBusDeviceProvider.add(address, device)) {
+    ALOGE("Failed to register bus device with addr %s", address.c_str());
+    return false;
+  }
+
+  if (!ensureDevicesFactory()) {
+    ALOGE("Failed to register audio devices factory.");
+    mBusDeviceProvider.removeAll();
+    return false;
+  }
+
+  return true;
+}
+
+bool AudioProxyDevicesManagerImpl::ensureDevicesFactory() {
+  sp<DevicesFactoryImpl> factory = mDevicesFactory.promote();
+  if (factory) {
+    return true;
+  }
+
+  factory = new DevicesFactoryImpl(mBusDeviceProvider);
+  status_t status = factory->registerAsService("audio_proxy");
+  if (status != OK) {
+    return false;
+  }
+
+  mDevicesFactory = factory;
+  return true;
 }
 
 }  // namespace service
diff --git a/audio_proxy/service/AudioProxyDevicesManagerImpl.h b/audio_proxy/service/AudioProxyDevicesManagerImpl.h
index 6fcbfab..ab2ea29 100644
--- a/audio_proxy/service/AudioProxyDevicesManagerImpl.h
+++ b/audio_proxy/service/AudioProxyDevicesManagerImpl.h
@@ -1,11 +1,28 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
+// Copyright (C) 2020 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.
 
-#ifndef DEVICE_GOOGLE_ATV_AUDIO_PROXY_SERVICE_AUDIO_PROXY_DEVICES_MANAGER_H_
-#define DEVICE_GOOGLE_ATV_AUDIO_PROXY_SERVICE_AUDIO_PROXY_DEVICES_MANAGER_H_
+#pragma once
 
+#include "BusDeviceProvider.h"
+#include "DevicesFactoryImpl.h"
+
+// clang-format off
 #include PATH(device/google/atv/audio_proxy/FILE_VERSION/IAudioProxyDevicesManager.h)
+// clang-format on
 
 using ::android::sp;
+using ::android::wp;
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 using ::device::google::atv::audio_proxy::CPP_VERSION::IAudioProxyDevicesManager;
@@ -21,9 +38,13 @@
 
   Return<bool> registerDevice(const hidl_string& address,
                               const sp<IBusDevice>& device) override;
+
+ private:
+  bool ensureDevicesFactory();
+
+  BusDeviceProvider mBusDeviceProvider;
+  wp<DevicesFactoryImpl> mDevicesFactory;
 };
 
 }  // namespace service
 }  // namespace audio_proxy
-
-#endif  // DEVICE_GOOGLE_ATV_AUDIO_PROXY_SERVICE_AUDIO_PROXY_DEVICES_MANAGER_H_
diff --git a/audio_proxy/service/BusDeviceProvider.cpp b/audio_proxy/service/BusDeviceProvider.cpp
new file mode 100644
index 0000000..adc92ff
--- /dev/null
+++ b/audio_proxy/service/BusDeviceProvider.cpp
@@ -0,0 +1,89 @@
+// Copyright (C) 2020 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 "BusDeviceProvider.h"
+
+#include <algorithm>
+
+namespace audio_proxy {
+namespace service {
+
+class BusDeviceProvider::DeathRecipient : public hidl_death_recipient {
+ public:
+  explicit DeathRecipient(BusDeviceProvider& owner) : mOwner(owner) {}
+  ~DeathRecipient() override = default;
+
+  void serviceDied(
+      uint64_t token,
+      const android::wp<::android::hidl::base::V1_0::IBase>& who) override {
+    mOwner.removeByToken(token);
+  }
+
+ private:
+  BusDeviceProvider& mOwner;
+};
+
+BusDeviceProvider::BusDeviceProvider()
+    : mDeathRecipient(new DeathRecipient(*this)) {}
+BusDeviceProvider::~BusDeviceProvider() = default;
+
+bool BusDeviceProvider::add(const hidl_string& address, sp<IBusDevice> device) {
+  std::lock_guard<std::mutex> guard(mDevicesLock);
+  auto it = std::find_if(mBusDevices.begin(), mBusDevices.end(),
+                         [&address](const BusDeviceHolder& holder) {
+                           return holder.address == address;
+                         });
+
+  if (it != mBusDevices.end()) {
+    return false;
+  }
+
+  uint64_t token = mNextToken++;
+
+  mBusDevices.push_back({device, address, token});
+
+  device->linkToDeath(mDeathRecipient, token);
+
+  return true;
+}
+
+sp<IBusDevice> BusDeviceProvider::get(const hidl_string& address) {
+  std::lock_guard<std::mutex> guard(mDevicesLock);
+  auto it = std::find_if(mBusDevices.begin(), mBusDevices.end(),
+                         [&address](const BusDeviceHolder& holder) {
+                           return holder.address == address;
+                         });
+
+  if (it == mBusDevices.end()) {
+    return nullptr;
+  }
+
+  return it->device;
+}
+
+void BusDeviceProvider::removeAll() {
+  std::lock_guard<std::mutex> guard(mDevicesLock);
+  mBusDevices.clear();
+}
+
+void BusDeviceProvider::removeByToken(uint64_t token) {
+  std::lock_guard<std::mutex> guard(mDevicesLock);
+  mBusDevices.erase(std::find_if(mBusDevices.begin(), mBusDevices.end(),
+                                 [token](const BusDeviceHolder& holder) {
+                                   return holder.token == token;
+                                 }));
+}
+
+}  // namespace service
+}  // namespace audio_proxy
\ No newline at end of file
diff --git a/audio_proxy/service/BusDeviceProvider.h b/audio_proxy/service/BusDeviceProvider.h
new file mode 100644
index 0000000..011161a
--- /dev/null
+++ b/audio_proxy/service/BusDeviceProvider.h
@@ -0,0 +1,72 @@
+// Copyright (C) 2020 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 <mutex>
+#include <vector>
+
+// clang-format off
+#include PATH(device/google/atv/audio_proxy/FILE_VERSION/IBusDevice.h)
+// clang-format on
+
+namespace audio_proxy {
+namespace service {
+
+using ::android::sp;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_string;
+using ::device::google::atv::audio_proxy::CPP_VERSION::IBusDevice;
+
+class BusDeviceProvider {
+ public:
+  BusDeviceProvider();
+  ~BusDeviceProvider();
+
+  // Register bus device under `address`. The device is unregistered when its
+  // process exits.
+  bool add(const hidl_string& address, sp<IBusDevice> device);
+
+  // Get IBusDevice with `address`. Caller should only keep the strong pointer
+  // shortly, a.k.a caller should release the strong pointer as soon as its
+  // function scope exits.
+  sp<IBusDevice> get(const hidl_string& address);
+
+  // Remove all the added devices.
+  void removeAll();
+
+ private:
+  class DeathRecipient;
+  struct BusDeviceHolder {
+    sp<IBusDevice> device;
+    hidl_string address;
+    uint64_t token;
+  };
+
+  friend class DeathRecipient;
+
+  // Called by DeathRecipient to remove device when the host process exits.
+  void removeByToken(uint64_t token);
+
+  sp<hidl_death_recipient> mDeathRecipient;
+
+  std::mutex mDevicesLock;
+
+  // Use a vector since we don't have too much registered devices.
+  std::vector<BusDeviceHolder> mBusDevices;
+  uint64_t mNextToken = 0;
+};
+
+}  // namespace service
+}  // namespace audio_proxy
\ No newline at end of file
diff --git a/audio_proxy/service/DeviceImpl.cpp b/audio_proxy/service/DeviceImpl.cpp
new file mode 100644
index 0000000..ac9936d
--- /dev/null
+++ b/audio_proxy/service/DeviceImpl.cpp
@@ -0,0 +1,155 @@
+// Copyright (C) 2020 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 "DeviceImpl.h"
+
+#include <utils/Log.h>
+
+#include "BusDeviceProvider.h"
+
+#undef LOG_TAG
+#define LOG_TAG "AudioProxyDeviceImpl"
+
+using namespace ::android::hardware::audio::CPP_VERSION;
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+
+namespace audio_proxy {
+namespace service {
+
+DeviceImpl::DeviceImpl(BusDeviceProvider& busDeviceProvider)
+    : mBusDeviceProvider(busDeviceProvider) {}
+
+// Methods from ::android::hardware::audio::V5_0::IDevice follow.
+Return<Result> DeviceImpl::initCheck() { return Result::OK; }
+
+Return<Result> DeviceImpl::setMasterVolume(float volume) {
+  // software mixer will emulate this ability
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getMasterVolume(getMasterVolume_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, 0.f);
+  return Void();
+}
+
+Return<Result> DeviceImpl::setMicMute(bool mute) {
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getMicMute(getMicMute_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, false);
+  return Void();
+}
+
+Return<Result> DeviceImpl::setMasterMute(bool mute) {
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getMasterMute(getMasterMute_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, false);
+  return Void();
+}
+
+Return<void> DeviceImpl::getInputBufferSize(const AudioConfig& config,
+                                            getInputBufferSize_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, 0);
+  return Void();
+}
+
+Return<void> DeviceImpl::openOutputStream(int32_t ioHandle,
+                                          const DeviceAddress& device,
+                                          const AudioConfig& config,
+                                          hidl_bitfield<AudioOutputFlag> flags,
+                                          const SourceMetadata& sourceMetadata,
+                                          openOutputStream_cb _hidl_cb) {
+  sp<IBusDevice> busDevice = mBusDeviceProvider.get(device.busAddress);
+
+  if (!busDevice) {
+    ALOGE("BusDevice with address %s was not found.",
+          device.busAddress.c_str());
+    _hidl_cb(Result::NOT_SUPPORTED, nullptr, config);
+    return Void();
+  }
+
+  return busDevice->openOutputStream(ioHandle, device, config, flags,
+                                     sourceMetadata, std::move(_hidl_cb));
+}
+
+Return<void> DeviceImpl::openInputStream(int32_t ioHandle,
+                                         const DeviceAddress& device,
+                                         const AudioConfig& config,
+                                         hidl_bitfield<AudioInputFlag> flags,
+                                         const SinkMetadata& sinkMetadata,
+                                         openInputStream_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, sp<IStreamIn>(), config);
+  return Void();
+}
+
+Return<bool> DeviceImpl::supportsAudioPatches() { return true; }
+
+Return<void> DeviceImpl::createAudioPatch(
+    const hidl_vec<AudioPortConfig>& sources,
+    const hidl_vec<AudioPortConfig>& sinks, createAudioPatch_cb _hidl_cb) {
+  _hidl_cb(Result::OK, 0);
+  return Void();
+}
+
+Return<Result> DeviceImpl::releaseAudioPatch(int32_t patch) {
+  return Result::OK;
+}
+
+Return<void> DeviceImpl::getAudioPort(const AudioPort& port,
+                                      getAudioPort_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, port);
+  return Void();
+}
+
+Return<Result> DeviceImpl::setAudioPortConfig(const AudioPortConfig& config) {
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getHwAvSync(getHwAvSync_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, 0);
+  return Void();
+}
+
+Return<Result> DeviceImpl::setScreenState(bool turnedOn) {
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getParameters(const hidl_vec<ParameterValue>& context,
+                                       const hidl_vec<hidl_string>& keys,
+                                       getParameters_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, hidl_vec<ParameterValue>());
+  return Void();
+}
+
+Return<Result> DeviceImpl::setParameters(
+    const hidl_vec<ParameterValue>& context,
+    const hidl_vec<ParameterValue>& parameters) {
+  return Result::NOT_SUPPORTED;
+}
+
+Return<void> DeviceImpl::getMicrophones(getMicrophones_cb _hidl_cb) {
+  _hidl_cb(Result::NOT_SUPPORTED, hidl_vec<MicrophoneInfo>());
+  return Void();
+}
+
+Return<Result> DeviceImpl::setConnectedState(const DeviceAddress& address,
+                                             bool connected) {
+  return Result::OK;
+}
+
+}  // namespace service
+}  // namespace audio_proxy
diff --git a/audio_proxy/service/DeviceImpl.h b/audio_proxy/service/DeviceImpl.h
new file mode 100644
index 0000000..3e2b9e4
--- /dev/null
+++ b/audio_proxy/service/DeviceImpl.h
@@ -0,0 +1,98 @@
+// Copyright (C) 2020 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
+
+// clang-format off
+#include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
+// clang-format on
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace audio_proxy {
+namespace service {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_bitfield;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::CPP_VERSION::AudioConfig;
+using ::android::hardware::audio::common::CPP_VERSION::AudioInputFlag;
+using ::android::hardware::audio::common::CPP_VERSION::AudioOutputFlag;
+using ::android::hardware::audio::common::CPP_VERSION::AudioPort;
+using ::android::hardware::audio::common::CPP_VERSION::AudioPortConfig;
+using ::android::hardware::audio::common::CPP_VERSION::DeviceAddress;
+using ::android::hardware::audio::common::CPP_VERSION::SinkMetadata;
+using ::android::hardware::audio::common::CPP_VERSION::SourceMetadata;
+using ::android::hardware::audio::CPP_VERSION::IDevice;
+using ::android::hardware::audio::CPP_VERSION::ParameterValue;
+using ::android::hardware::audio::CPP_VERSION::Result;
+
+class BusDeviceProvider;
+
+class DeviceImpl : public IDevice {
+ public:
+  explicit DeviceImpl(BusDeviceProvider& busDeviceProvider);
+
+  // Methods from ::android::hardware::audio::V5_0::IDevice follow.
+  Return<Result> initCheck() override;
+  Return<Result> setMasterVolume(float volume) override;
+  Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb) override;
+  Return<Result> setMicMute(bool mute) override;
+  Return<void> getMicMute(getMicMute_cb _hidl_cb) override;
+  Return<Result> setMasterMute(bool mute) override;
+  Return<void> getMasterMute(getMasterMute_cb _hidl_cb) override;
+  Return<void> getInputBufferSize(const AudioConfig& config,
+                                  getInputBufferSize_cb _hidl_cb) override;
+  Return<void> openOutputStream(int32_t ioHandle, const DeviceAddress& device,
+                                const AudioConfig& config,
+                                hidl_bitfield<AudioOutputFlag> flags,
+                                const SourceMetadata& sourceMetadata,
+                                openOutputStream_cb _hidl_cb) override;
+  Return<void> openInputStream(int32_t ioHandle, const DeviceAddress& device,
+                               const AudioConfig& config,
+                               hidl_bitfield<AudioInputFlag> flags,
+                               const SinkMetadata& sinkMetadata,
+                               openInputStream_cb _hidl_cb) override;
+  Return<bool> supportsAudioPatches() override;
+  Return<void> createAudioPatch(const hidl_vec<AudioPortConfig>& sources,
+                                const hidl_vec<AudioPortConfig>& sinks,
+                                createAudioPatch_cb _hidl_cb) override;
+  Return<Result> releaseAudioPatch(int32_t patch) override;
+  Return<void> getAudioPort(const AudioPort& port,
+                            getAudioPort_cb _hidl_cb) override;
+  Return<Result> setAudioPortConfig(const AudioPortConfig& config) override;
+  Return<void> getHwAvSync(getHwAvSync_cb _hidl_cb) override;
+  Return<Result> setScreenState(bool turnedOn) override;
+  Return<void> getParameters(const hidl_vec<ParameterValue>& context,
+                             const hidl_vec<hidl_string>& keys,
+                             getParameters_cb _hidl_cb) override;
+  Return<Result> setParameters(
+      const hidl_vec<ParameterValue>& context,
+      const hidl_vec<ParameterValue>& parameters) override;
+  Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
+  Return<Result> setConnectedState(const DeviceAddress& address,
+                                   bool connected) override;
+
+ private:
+  BusDeviceProvider& mBusDeviceProvider;
+};
+
+}  // namespace service
+}  // namespace audio_proxy
diff --git a/audio_proxy/service/DevicesFactoryImpl.cpp b/audio_proxy/service/DevicesFactoryImpl.cpp
new file mode 100644
index 0000000..37963c4
--- /dev/null
+++ b/audio_proxy/service/DevicesFactoryImpl.cpp
@@ -0,0 +1,52 @@
+// Copyright (C) 2020 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 "DevicesFactoryImpl.h"
+
+#include <utils/Log.h>
+
+#undef LOG_TAG
+#define LOG_TAG "AudioProxyDevicesManagerImpl"
+
+using namespace ::android::hardware::audio::CPP_VERSION;
+
+namespace audio_proxy {
+namespace service {
+
+DevicesFactoryImpl::DevicesFactoryImpl(BusDeviceProvider& busDeviceProvider)
+    : mBusDeviceProvider(busDeviceProvider) {}
+
+// Methods from ::android::hardware::audio::V5_0::IDevicesFactory follow.
+Return<void> DevicesFactoryImpl::openDevice(const hidl_string& device,
+                                            openDevice_cb _hidl_cb) {
+  ALOGE("openDevice");
+  if (device == "audio_proxy") {
+    ALOGE("Audio Device was opened: %s", device.c_str());
+    _hidl_cb(Result::OK, new DeviceImpl(mBusDeviceProvider));
+  } else {
+    _hidl_cb(Result::NOT_SUPPORTED, nullptr);
+  }
+
+  return Void();
+}
+
+Return<void> DevicesFactoryImpl::openPrimaryDevice(
+    openPrimaryDevice_cb _hidl_cb) {
+  // The AudioProxy HAL does not support a primary device.
+  _hidl_cb(Result::NOT_SUPPORTED, nullptr);
+  return Void();
+}
+
+}  // namespace service
+}  // namespace audio_proxy
diff --git a/audio_proxy/service/DevicesFactoryImpl.h b/audio_proxy/service/DevicesFactoryImpl.h
new file mode 100644
index 0000000..b8dbf87
--- /dev/null
+++ b/audio_proxy/service/DevicesFactoryImpl.h
@@ -0,0 +1,53 @@
+// Copyright (C) 2020 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
+
+// clang-format off
+#include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
+// clang-format on
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include "DeviceImpl.h"
+
+namespace audio_proxy {
+namespace service {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::V5_0::IDevicesFactory;
+
+class BusDeviceProvider;
+
+class DevicesFactoryImpl : public IDevicesFactory {
+ public:
+  explicit DevicesFactoryImpl(BusDeviceProvider& busDeviceProvider);
+
+  // Methods from ::android::hardware::audio::V5_0::IDevicesFactory follow.
+  Return<void> openDevice(const hidl_string& device,
+                          openDevice_cb _hidl_cb) override;
+  Return<void> openPrimaryDevice(openPrimaryDevice_cb _hidl_cb) override;
+
+ private:
+  BusDeviceProvider& mBusDeviceProvider;
+};
+
+}  // namespace service
+}  // namespace audio_proxy
diff --git a/audio_proxy/service/main.cpp b/audio_proxy/service/main.cpp
index 95fe4eb..77eedb7 100644
--- a/audio_proxy/service/main.cpp
+++ b/audio_proxy/service/main.cpp
@@ -1,4 +1,16 @@
-// Copyright 2020 Google Inc. All Rights Reserved.
+// Copyright (C) 2020 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 LOG_TAG "audio_proxy_service"
 
@@ -6,16 +18,24 @@
 #include <utils/Log.h>
 
 #include "AudioProxyDevicesManagerImpl.h"
+#include "DevicesFactoryImpl.h"
 
 using ::android::sp;
 using ::android::status_t;
+using ::audio_proxy::service::DevicesFactoryImpl;
+
+namespace {
+status_t registerAudioProxyDevicesManager() {
+  sp<audio_proxy::service::AudioProxyDevicesManagerImpl> manager =
+      new audio_proxy::service::AudioProxyDevicesManagerImpl();
+  return manager->registerAsService();
+}
+}  // namespace
 
 int main(int argc, char** argv) {
   android::hardware::configureRpcThreadpool(1, true /* callerWillJoin */);
 
-  sp<audio_proxy::service::AudioProxyDevicesManagerImpl> manager =
-      new audio_proxy::service::AudioProxyDevicesManagerImpl();
-  status_t status = manager->registerAsService();
+  status_t status = registerAudioProxyDevicesManager();
   if (status != android::OK) {
     ALOGE("fail to register devices factory manager: %x", status);
     return -1;