blob: 81b6b4f4e777adaea6e19ff9fc879511325e9b7a [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ui/scenic/lib/flatland/flatland_manager.h"
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fit/function.h>
namespace flatland {
FlatlandManager::FlatlandManager(
const std::shared_ptr<FlatlandPresenter>& flatland_presenter,
const std::shared_ptr<UberStructSystem>& uber_struct_system,
const std::shared_ptr<LinkSystem>& link_system,
const std::vector<std::shared_ptr<BufferCollectionImporter>>& buffer_collection_importers)
: flatland_presenter_(flatland_presenter),
uber_struct_system_(uber_struct_system),
link_system_(link_system),
buffer_collection_importers_(buffer_collection_importers) {}
void FlatlandManager::CreateFlatland(
fidl::InterfaceRequest<fuchsia::ui::scenic::internal::Flatland> request) {
const scheduling::SessionId id = uber_struct_system_->GetNextInstanceId();
FX_DCHECK(flatland_instances_.find(id) == flatland_instances_.end());
fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator;
zx_status_t status = fdio_service_connect("/svc/fuchsia.sysmem.Allocator",
sysmem_allocator.NewRequest().TakeChannel().release());
FX_DCHECK(status == ZX_OK);
auto flatland = std::make_unique<Flatland>(
id, flatland_presenter_, link_system_, uber_struct_system_->AllocateQueueForSession(id),
buffer_collection_importers_, std::move(sysmem_allocator));
auto result = flatland_instances_.emplace(
id, std::make_unique<FlatlandInstance>(request.channel(), std::move(flatland)));
FX_DCHECK(result.second);
auto& instance = result.first->second;
instance->binding.Bind(std::move(request), instance->loop.dispatcher());
// Run the waiter on the main thread, not the instance thread, so that it can clean up and join
// the instance thread.
status = instance->peer_closed_waiter.Begin(
async_get_default_dispatcher(),
[this, id](async_dispatcher_t* dispatcher, async::WaitOnce* wait, zx_status_t status,
const zx_packet_signal_t* signal) { this->RemoveFlatlandInstance(id); });
FX_DCHECK(status == ZX_OK);
const std::string name = "Flatland ID=" + std::to_string(id);
status = instance->loop.StartThread(name.c_str());
FX_DCHECK(status == ZX_OK);
}
size_t FlatlandManager::GetSessionCount() const { return flatland_instances_.size(); }
void FlatlandManager::RemoveFlatlandInstance(scheduling::SessionId session_id) {
auto instance_kv = flatland_instances_.find(session_id);
FX_DCHECK(instance_kv != flatland_instances_.end());
// The fidl::Binding must be destroyed on the thread that owns the looper it is bound to. Remove
// the instance from the map, then push cleanup onto the worker thread. Note that the closure
// exists only to transfer the cleanup responsibilities to the worker thread.
async::PostTask(instance_kv->second->loop.dispatcher(),
[instance = std::move(instance_kv->second)]() {});
// Other resource cleanup can safely occur on the main thread.
flatland_instances_.erase(session_id);
uber_struct_system_->RemoveSession(session_id);
}
} // namespace flatland