diff options
19 files changed, 0 insertions, 4875 deletions
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp deleted file mode 100644 index e265f15941..0000000000 --- a/libs/vr/libvrflinger/Android.bp +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (C) 2008 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. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -sourceFiles = [ - "acquired_buffer.cpp", - "epoll_event_dispatcher.cpp", - "display_manager_service.cpp", - "display_service.cpp", - "display_surface.cpp", - "hardware_composer.cpp", - "vr_flinger.cpp", -] - -includeFiles = ["include"] - -staticLibraries = [ - "libdisplay", - "libdvrcommon", - "libperformance", - "libvrsensor", - "libbroadcastring", - "libvr_manager", - "libbroadcastring", - "libaidlcommonsupport", -] - -sharedLibraries = [ - "android.frameworks.vr.composer@2.0", - "android.hardware.graphics.allocator@2.0", - "android.hardware.graphics.composer@2.1", - "android.hardware.graphics.composer@2.2", - "android.hardware.graphics.composer@2.3", - "android.hardware.graphics.composer@2.4", - "android.hardware.graphics.composer3-V1-ndk", - "libbinder", - "libbinder_ndk", - "libbase", - "libbufferhubqueue", - "libcutils", - "liblog", - "libhardware", - "libnativewindow", - "libprocessgroup", - "libutils", - "libEGL", - "libGLESv1_CM", - "libGLESv2", - "libvulkan", - "libui", - "libgui", - "libsync", - "libhidlbase", - "libfmq", - "libpdx_default_transport", -] - -headerLibraries = [ - "android.hardware.graphics.composer@2.1-command-buffer", - "android.hardware.graphics.composer@2.2-command-buffer", - "android.hardware.graphics.composer@2.3-command-buffer", - "android.hardware.graphics.composer@2.4-command-buffer", - "android.hardware.graphics.composer3-command-buffer", - "libdvr_headers", - "libsurfaceflinger_headers", -] - -cc_library_static { - srcs: sourceFiles, - export_include_dirs: includeFiles, - - clang: true, - cflags: [ - "-DLOG_TAG=\"vr_flinger\"", - "-DTRACE=0", - "-DATRACE_TAG=ATRACE_TAG_GRAPHICS", - "-DGL_GLEXT_PROTOTYPES", - "-DEGL_EGLEXT_PROTOTYPES", - "-Wall", - "-Werror", - "-Wno-error=sign-compare", // to fix later - "-Wno-unused-variable", - ], - shared_libs: sharedLibraries, - whole_static_libs: staticLibraries, - header_libs: headerLibraries, - name: "libvrflinger", -} - -subdirs = [ - "tests", -] diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp deleted file mode 100644 index c360deed5b..0000000000 --- a/libs/vr/libvrflinger/acquired_buffer.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "acquired_buffer.h" - -#include <log/log.h> -#include <sync/sync.h> - -using android::pdx::LocalHandle; - -namespace android { -namespace dvr { - -AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, - LocalHandle acquire_fence, std::size_t slot) - : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {} - -AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, - int* error) { - LocalHandle fence; - const int ret = buffer->Acquire(&fence); - - if (error) - *error = ret; - - if (ret < 0) { - ALOGW("AcquiredBuffer::AcquiredBuffer: Failed to acquire buffer: %s", - strerror(-ret)); - buffer_ = nullptr; - // Default construct sets acquire_fence_ to empty. - } else { - buffer_ = buffer; - acquire_fence_ = std::move(fence); - } -} - -AcquiredBuffer::AcquiredBuffer(AcquiredBuffer&& other) noexcept { - *this = std::move(other); -} - -AcquiredBuffer::~AcquiredBuffer() { Release(LocalHandle(kEmptyFence)); } - -AcquiredBuffer& AcquiredBuffer::operator=(AcquiredBuffer&& other) noexcept { - if (this != &other) { - Release(); - - using std::swap; - swap(buffer_, other.buffer_); - swap(acquire_fence_, other.acquire_fence_); - swap(slot_, other.slot_); - } - return *this; -} - -bool AcquiredBuffer::IsAvailable() const { - if (IsEmpty()) - return false; - - // Only check the fence if the acquire fence is not empty. - if (acquire_fence_) { - const int ret = sync_wait(acquire_fence_.Get(), 0); - ALOGD_IF(TRACE || (ret < 0 && errno != ETIME), - "AcquiredBuffer::IsAvailable: buffer_id=%d acquire_fence=%d " - "sync_wait()=%d errno=%d.", - buffer_->id(), acquire_fence_.Get(), ret, ret < 0 ? errno : 0); - if (ret == 0) { - // The fence is completed, so to avoid further calls to sync_wait we close - // it here. - acquire_fence_.Close(); - } - return ret == 0; - } else { - return true; - } -} - -LocalHandle AcquiredBuffer::ClaimAcquireFence() { - return std::move(acquire_fence_); -} - -std::shared_ptr<ConsumerBuffer> AcquiredBuffer::ClaimBuffer() { - return std::move(buffer_); -} - -int AcquiredBuffer::Release(LocalHandle release_fence) { - ALOGD_IF(TRACE, "AcquiredBuffer::Release: buffer_id=%d release_fence=%d", - buffer_ ? buffer_->id() : -1, release_fence.Get()); - if (buffer_) { - const int ret = buffer_->ReleaseAsync(); - if (ret < 0) { - ALOGE("AcquiredBuffer::Release: Failed to release buffer %d: %s", - buffer_->id(), strerror(-ret)); - if (ret != -ESHUTDOWN) - return ret; - } - - buffer_ = nullptr; - } - - acquire_fence_.Close(); - slot_ = 0; - return 0; -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h deleted file mode 100644 index 7643e75ecf..0000000000 --- a/libs/vr/libvrflinger/acquired_buffer.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_ACQUIRED_BUFFER_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_ACQUIRED_BUFFER_H_ - -#include <pdx/file_handle.h> -#include <private/dvr/consumer_buffer.h> - -#include <memory> - -namespace android { -namespace dvr { - -// Manages the ACQUIRE/RELEASE ownership cycle of a ConsumerBuffer. -class AcquiredBuffer { - public: - static constexpr int kEmptyFence = pdx::LocalHandle::kEmptyFileHandle; - - AcquiredBuffer() : buffer_(nullptr), acquire_fence_(kEmptyFence) {} - - // Constructs an AcquiredBuffer from a ConsumerBuffer pointer and an acquire - // fence. The ConsumerBuffer MUST be in the ACQUIRED state prior to calling - // this constructor; the constructor does not attempt to ACQUIRE the buffer - // itself. - AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, - pdx::LocalHandle acquire_fence, std::size_t slot = 0); - - // Constructs an AcquiredBuffer from a ConsumerBuffer. The ConsumerBuffer MUST - // be in the POSTED state prior to calling this constructor, as this - // constructor attempts to ACQUIRE the buffer. If ACQUIRING the buffer fails - // this instance is left in the empty state. An optional error code is - // returned in |error|, which may be nullptr if not needed. - AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, int* error); - - // Move constructor. Behaves similarly to the move assignment operator below. - AcquiredBuffer(AcquiredBuffer&& other) noexcept; - - ~AcquiredBuffer(); - - // Move assignment operator. Moves the ConsumerBuffer and acquire fence from - // |other| into this instance after RELEASING the current ConsumerBuffer and - // closing the acquire fence. After the move |other| is left in the empty - // state. - AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept; - - // Accessors for the underlying ConsumerBuffer, the acquire fence, and the - // use-case specific sequence value from the acquisition (see - // private/dvr/consumer_buffer.h). - std::shared_ptr<ConsumerBuffer> buffer() const { return buffer_; } - int acquire_fence() const { return acquire_fence_.Get(); } - - // When non-empty, returns true if the acquired fence was signaled (or if the - // fence is empty). Returns false when empty or if the fence is not signaled. - bool IsAvailable() const; - - bool IsEmpty() const { return buffer_ == nullptr; } - - // Returns the acquire fence, passing ownership to the caller. - pdx::LocalHandle ClaimAcquireFence(); - - // Returns the buffer, passing ownership to the caller. Caller is responsible - // for calling Release on the returned buffer. - std::shared_ptr<ConsumerBuffer> ClaimBuffer(); - - // Releases the ConsumerBuffer, passing the release fence in |release_fence| - // to the producer. On success, the ConsumerBuffer and acquire fence are set - // to empty state; if release fails, the ConsumerBuffer and acquire fence are - // left in place and a negative error code is returned. - int Release(pdx::LocalHandle release_fence = {}); - - // Returns the slot in the queue this buffer belongs to. Buffers that are not - // part of a queue return 0. - std::size_t slot() const { return slot_; } - - private: - std::shared_ptr<ConsumerBuffer> buffer_; - // Mutable so that the fence can be closed when it is determined to be - // signaled during IsAvailable(). - mutable pdx::LocalHandle acquire_fence_; - std::size_t slot_{0}; - - AcquiredBuffer(const AcquiredBuffer&) = delete; - void operator=(const AcquiredBuffer&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_ACQUIRED_BUFFER_H_ diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp deleted file mode 100644 index 34b3b0a6f4..0000000000 --- a/libs/vr/libvrflinger/display_manager_service.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "display_manager_service.h" - -#include <pdx/channel_handle.h> -#include <pdx/default_transport/service_endpoint.h> -#include <private/android_filesystem_config.h> -#include <private/dvr/display_protocol.h> -#include <private/dvr/trusted_uids.h> -#include <sys/poll.h> - -#include <array> - -using android::dvr::display::DisplayManagerProtocol; -using android::pdx::Channel; -using android::pdx::LocalChannelHandle; -using android::pdx::Message; -using android::pdx::default_transport::Endpoint; -using android::pdx::ErrorStatus; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::rpc::IfAnyOf; -using android::pdx::rpc::RemoteMethodError; - -namespace android { -namespace dvr { - -void DisplayManager::SetNotificationsPending(bool pending) { - auto status = service_->ModifyChannelEvents(channel_id_, pending ? 0 : POLLIN, - pending ? POLLIN : 0); - ALOGE_IF(!status, - "DisplayManager::SetNotificationPending: Failed to modify channel " - "events: %s", - status.GetErrorMessage().c_str()); -} - -DisplayManagerService::DisplayManagerService( - const std::shared_ptr<DisplayService>& display_service) - : BASE("DisplayManagerService", - Endpoint::Create(DisplayManagerProtocol::kClientPath)), - display_service_(display_service) { - display_service_->SetDisplayConfigurationUpdateNotifier( - std::bind(&DisplayManagerService::OnDisplaySurfaceChange, this)); -} - -std::shared_ptr<pdx::Channel> DisplayManagerService::OnChannelOpen( - pdx::Message& message) { - const int user_id = message.GetEffectiveUserId(); - const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); - - // Check if the display_manager_ has a defunct channel. - if (display_manager_ && !HasChannelId(display_manager_->channel_id())) { - ALOGE("DisplayManagerService::OnChannelOpen: Found defunct channel %d with " - "no OnChannelClose, clearing prior display manager.", - display_manager_->channel_id()); - display_manager_ = nullptr; - } - - // Prevent more than one display manager from registering at a time or - // untrusted UIDs from connecting. - if (display_manager_ || !trusted) { - RemoteMethodError(message, EPERM); - return nullptr; - } - - display_manager_ = - std::make_shared<DisplayManager>(this, message.GetChannelId()); - return display_manager_; -} - -void DisplayManagerService::OnChannelClose( - pdx::Message& /*message*/, const std::shared_ptr<pdx::Channel>& channel) { - // Unregister the display manager when the channel closes. - if (display_manager_ == channel) - display_manager_ = nullptr; -} - -pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) { - ATRACE_NAME("DisplayManagerService::HandleMessage"); - auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel()); - - switch (message.GetOp()) { - case DisplayManagerProtocol::GetSurfaceState::Opcode: - DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceState>( - *this, &DisplayManagerService::OnGetSurfaceState, message); - return {}; - - case DisplayManagerProtocol::GetSurfaceQueue::Opcode: - DispatchRemoteMethod<DisplayManagerProtocol::GetSurfaceQueue>( - *this, &DisplayManagerService::OnGetSurfaceQueue, message); - return {}; - - default: - return Service::DefaultHandleMessage(message); - } -} - -pdx::Status<std::vector<display::SurfaceState>> -DisplayManagerService::OnGetSurfaceState(pdx::Message& /*message*/) { - std::vector<display::SurfaceState> items; - - display_service_->ForEachDisplaySurface( - SurfaceType::Application, - [&items](const std::shared_ptr<DisplaySurface>& surface) mutable { - items.push_back({surface->surface_id(), surface->process_id(), - surface->user_id(), surface->attributes(), - surface->update_flags(), surface->GetQueueIds()}); - surface->ClearUpdate(); - }); - - // The fact that we're in the message handler implies that display_manager_ is - // not nullptr. No check required, unless this service becomes multi-threaded. - display_manager_->SetNotificationsPending(false); - return items; -} - -pdx::Status<pdx::LocalChannelHandle> DisplayManagerService::OnGetSurfaceQueue( - pdx::Message& /*message*/, int surface_id, int queue_id) { - auto surface = display_service_->GetDisplaySurface(surface_id); - if (!surface || surface->surface_type() != SurfaceType::Application) - return ErrorStatus(EINVAL); - - auto queue = - std::static_pointer_cast<ApplicationDisplaySurface>(surface)->GetQueue( - queue_id); - if (!queue) - return ErrorStatus(EINVAL); - - auto status = queue->CreateConsumerQueueHandle(); - ALOGE_IF( - !status, - "DisplayManagerService::OnGetSurfaceQueue: Failed to create consumer " - "queue for queue_id=%d: %s", - queue->id(), status.GetErrorMessage().c_str()); - - return status; -} - -void DisplayManagerService::OnDisplaySurfaceChange() { - if (display_manager_) - display_manager_->SetNotificationsPending(true); -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h deleted file mode 100644 index 3133fe1884..0000000000 --- a/libs/vr/libvrflinger/display_manager_service.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_ -#define ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_ - -#include <pdx/service.h> -#include <pdx/status.h> -#include <private/dvr/display_protocol.h> - -#include "display_service.h" - -namespace android { -namespace dvr { - -class DisplayManagerService; - -// The display manager is a client of the display manager service. This class -// represents the connected client that the display manager service sends -// notifications to. -class DisplayManager : public pdx::Channel { - public: - DisplayManager(DisplayManagerService* service, int channel_id) - : service_(service), channel_id_(channel_id) {} - - int channel_id() const { return channel_id_; } - - // Sets or clears the channel event mask to indicate pending events that the - // display manager on the other end of the channel should read and handle. - // When |pending| is true the POLLIN bit is set in the event mask; when - // |pending| is false the POLLIN bit is cleared in the event mask. - void SetNotificationsPending(bool pending); - - private: - DisplayManager(const DisplayManager&) = delete; - void operator=(const DisplayManager&) = delete; - - DisplayManagerService* service_; - int channel_id_; -}; - -// The display manager service marshalls state and events from the display -// service to the display manager. -class DisplayManagerService : public pdx::ServiceBase<DisplayManagerService> { - public: - std::shared_ptr<pdx::Channel> OnChannelOpen(pdx::Message& message) override; - void OnChannelClose(pdx::Message& message, - const std::shared_ptr<pdx::Channel>& channel) override; - pdx::Status<void> HandleMessage(pdx::Message& message) override; - - private: - friend BASE; - - explicit DisplayManagerService( - const std::shared_ptr<DisplayService>& display_service); - - pdx::Status<std::vector<display::SurfaceState>> OnGetSurfaceState( - pdx::Message& message); - pdx::Status<pdx::LocalChannelHandle> OnGetSurfaceQueue(pdx::Message& message, - int surface_id, - int queue_id); - - // Called by the display service to indicate changes to display surfaces that - // the display manager should evaluate. - void OnDisplaySurfaceChange(); - - DisplayManagerService(const DisplayManagerService&) = delete; - void operator=(const DisplayManagerService&) = delete; - - std::shared_ptr<DisplayService> display_service_; - std::shared_ptr<DisplayManager> display_manager_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_VRFLINGER_DISPLAY_MANAGER_SERVICE_H_ diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp deleted file mode 100644 index 582fed3a4a..0000000000 --- a/libs/vr/libvrflinger/display_service.cpp +++ /dev/null @@ -1,437 +0,0 @@ -#include "display_service.h" - -#include <unistd.h> - -#include <algorithm> -#include <sstream> -#include <string> -#include <vector> - -#include <android-base/file.h> -#include <android-base/properties.h> -#include <dvr/dvr_display_types.h> -#include <pdx/default_transport/service_endpoint.h> -#include <pdx/rpc/remote_method.h> -#include <private/android_filesystem_config.h> -#include <private/dvr/display_protocol.h> -#include <private/dvr/numeric.h> -#include <private/dvr/trusted_uids.h> -#include <private/dvr/types.h> - -#include "DisplayHardware/DisplayIdentification.h" - -using android::dvr::display::DisplayProtocol; -using android::pdx::Channel; -using android::pdx::ErrorStatus; -using android::pdx::Message; -using android::pdx::Status; -using android::pdx::default_transport::Endpoint; -using android::pdx::rpc::DispatchRemoteMethod; - -namespace { - -const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics"; -const char kDvrDeviceMetricsProperty[] = "ro.dvr.device_metrics"; -const char kDvrDeviceConfigProperty[] = "ro.dvr.device_configuration"; - -} // namespace - -namespace android { -namespace dvr { - -DisplayService::DisplayService(Hwc2::Composer* hidl, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback) - : BASE("DisplayService", - Endpoint::Create(display::DisplayProtocol::kClientPath)) { - hardware_composer_.Initialize( - hidl, primary_display_id, request_display_callback); -} - -bool DisplayService::IsInitialized() const { - return BASE::IsInitialized() && hardware_composer_.IsInitialized(); -} - -std::string DisplayService::DumpState(size_t /*max_length*/) { - std::ostringstream stream; - - auto surfaces = GetDisplaySurfaces(); - std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) { - return a->surface_id() < b->surface_id(); - }); - - stream << "Application Surfaces:" << std::endl; - - size_t count = 0; - for (const auto& surface : surfaces) { - if (surface->surface_type() == SurfaceType::Application) { - stream << "Surface " << count++ << ":"; - stream << " surface_id=" << surface->surface_id() - << " process_id=" << surface->process_id() - << " user_id=" << surface->user_id() - << " visible=" << surface->visible() - << " z_order=" << surface->z_order(); - - stream << " queue_ids="; - auto queue_ids = surface->GetQueueIds(); - std::sort(queue_ids.begin(), queue_ids.end()); - for (int32_t id : queue_ids) { - if (id != queue_ids[0]) - stream << ","; - stream << id; - } - stream << std::endl; - } - } - stream << std::endl; - - stream << "Direct Surfaces:" << std::endl; - - count = 0; - for (const auto& surface : surfaces) { - if (surface->surface_type() == SurfaceType::Direct) { - stream << "Surface " << count++ << ":"; - stream << " surface_id=" << surface->surface_id() - << " process_id=" << surface->process_id() - << " user_id=" << surface->user_id() - << " visible=" << surface->visible() - << " z_order=" << surface->z_order(); - - stream << " queue_ids="; - auto queue_ids = surface->GetQueueIds(); - std::sort(queue_ids.begin(), queue_ids.end()); - for (int32_t id : queue_ids) { - if (id != queue_ids[0]) - stream << ","; - stream << id; - } - stream << std::endl; - } - } - stream << std::endl; - - stream << hardware_composer_.Dump(); - return stream.str(); -} - -void DisplayService::OnChannelClose(pdx::Message& message, - const std::shared_ptr<Channel>& channel) { - if (auto surface = std::static_pointer_cast<DisplaySurface>(channel)) { - surface->OnSetAttributes(message, - {{display::SurfaceAttribute::Visible, - display::SurfaceAttributeValue{false}}}); - } -} - -// First-level dispatch for display service messages. Directly handles messages -// that are independent of the display surface (metrics, creation) and routes -// surface-specific messages to the per-instance handlers. -Status<void> DisplayService::HandleMessage(pdx::Message& message) { - ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp()); - ATRACE_NAME("DisplayService::HandleMessage"); - - switch (message.GetOp()) { - case DisplayProtocol::GetMetrics::Opcode: - DispatchRemoteMethod<DisplayProtocol::GetMetrics>( - *this, &DisplayService::OnGetMetrics, message); - return {}; - - case DisplayProtocol::GetConfigurationData::Opcode: - DispatchRemoteMethod<DisplayProtocol::GetConfigurationData>( - *this, &DisplayService::OnGetConfigurationData, message); - return {}; - - case DisplayProtocol::GetDisplayIdentificationPort::Opcode: - DispatchRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>( - *this, &DisplayService::OnGetDisplayIdentificationPort, message); - return {}; - - case DisplayProtocol::CreateSurface::Opcode: - DispatchRemoteMethod<DisplayProtocol::CreateSurface>( - *this, &DisplayService::OnCreateSurface, message); - return {}; - - case DisplayProtocol::SetupGlobalBuffer::Opcode: - DispatchRemoteMethod<DisplayProtocol::SetupGlobalBuffer>( - *this, &DisplayService::OnSetupGlobalBuffer, message); - return {}; - - case DisplayProtocol::DeleteGlobalBuffer::Opcode: - DispatchRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>( - *this, &DisplayService::OnDeleteGlobalBuffer, message); - return {}; - - case DisplayProtocol::GetGlobalBuffer::Opcode: - DispatchRemoteMethod<DisplayProtocol::GetGlobalBuffer>( - *this, &DisplayService::OnGetGlobalBuffer, message); - return {}; - - case DisplayProtocol::IsVrAppRunning::Opcode: - DispatchRemoteMethod<DisplayProtocol::IsVrAppRunning>( - *this, &DisplayService::IsVrAppRunning, message); - return {}; - - // Direct the surface specific messages to the surface instance. - case DisplayProtocol::SetAttributes::Opcode: - case DisplayProtocol::CreateQueue::Opcode: - case DisplayProtocol::GetSurfaceInfo::Opcode: - return HandleSurfaceMessage(message); - - default: - return Service::HandleMessage(message); - } -} - -Status<display::Metrics> DisplayService::OnGetMetrics( - pdx::Message& /*message*/) { - const auto& params = hardware_composer_.GetPrimaryDisplayParams(); - return {{static_cast<uint32_t>(params.width), - static_cast<uint32_t>(params.height), - static_cast<uint32_t>(params.dpi.x), - static_cast<uint32_t>(params.dpi.y), - static_cast<uint32_t>(params.vsync_period_ns), - 0, - 0, - 0, - 0.0, - {}, - {}}}; -} - -pdx::Status<std::string> DisplayService::OnGetConfigurationData( - pdx::Message& /*message*/, display::ConfigFileType config_type) { - std::string property_name; - DisplayIdentificationData display_identification_data; - switch (config_type) { - case display::ConfigFileType::kLensMetrics: - property_name = kDvrLensMetricsProperty; - break; - case display::ConfigFileType::kDeviceMetrics: - property_name = kDvrDeviceMetricsProperty; - break; - case display::ConfigFileType::kDeviceConfiguration: - property_name = kDvrDeviceConfigProperty; - break; - case display::ConfigFileType::kDeviceEdid: - display_identification_data = - hardware_composer_.GetCurrentDisplayIdentificationData(); - if (display_identification_data.size() == 0) { - return ErrorStatus(ENOENT); - } - return std::string(display_identification_data.begin(), - display_identification_data.end()); - default: - return ErrorStatus(EINVAL); - } - std::string file_path = base::GetProperty(property_name, ""); - if (file_path.empty()) { - return ErrorStatus(ENOENT); - } - - std::string data; - if (!base::ReadFileToString(file_path, &data)) { - return ErrorStatus(errno); - } - - return std::move(data); -} - -pdx::Status<uint8_t> DisplayService::OnGetDisplayIdentificationPort( - pdx::Message& /*message*/) { - return hardware_composer_.GetCurrentDisplayPort(); -} - -// Creates a new DisplaySurface and associates it with this channel. This may -// only be done once per channel. -Status<display::SurfaceInfo> DisplayService::OnCreateSurface( - pdx::Message& message, const display::SurfaceAttributes& attributes) { - // A surface may only be created once per channel. - if (message.GetChannel()) - return ErrorStatus(EINVAL); - - ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d", - message.GetChannelId()); - - // Use the channel id as the unique surface id. - const int surface_id = message.GetChannelId(); - const int process_id = message.GetProcessId(); - const int user_id = message.GetEffectiveUserId(); - - ALOGI_IF(TRACE, - "DisplayService::OnCreateSurface: surface_id=%d process_id=%d", - surface_id, process_id); - - auto surface_status = - DisplaySurface::Create(this, surface_id, process_id, user_id, attributes); - if (!surface_status) { - ALOGE("DisplayService::OnCreateSurface: Failed to create surface: %s", - surface_status.GetErrorMessage().c_str()); - return ErrorStatus(surface_status.error()); - } - auto surface = surface_status.take(); - message.SetChannel(surface); - - // Update the surface with the attributes supplied with the create call. For - // application surfaces this has the side effect of notifying the display - // manager of the new surface. For direct surfaces, this may trigger a mode - // change, depending on the value of the visible attribute. - surface->OnSetAttributes(message, attributes); - - return {{surface->surface_id(), surface->visible(), surface->z_order()}}; -} - -void DisplayService::SurfaceUpdated(SurfaceType surface_type, - display::SurfaceUpdateFlags update_flags) { - ALOGD_IF(TRACE, "DisplayService::SurfaceUpdated: update_flags=%x", - update_flags.value()); - if (update_flags.value() != 0) { - if (surface_type == SurfaceType::Application) - NotifyDisplayConfigurationUpdate(); - else - UpdateActiveDisplaySurfaces(); - } -} - -pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnSetupGlobalBuffer( - pdx::Message& message, DvrGlobalBufferKey key, size_t size, - uint64_t usage) { - const int user_id = message.GetEffectiveUserId(); - const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); - - if (!trusted) { - ALOGE( - "DisplayService::OnSetupGlobalBuffer: Permission denied for user_id=%d", - user_id); - return ErrorStatus(EPERM); - } - return SetupGlobalBuffer(key, size, usage); -} - -pdx::Status<void> DisplayService::OnDeleteGlobalBuffer(pdx::Message& message, - DvrGlobalBufferKey key) { - const int user_id = message.GetEffectiveUserId(); - const bool trusted = (user_id == AID_ROOT) || IsTrustedUid(user_id); - - if (!trusted) { - ALOGE( - "DisplayService::OnDeleteGlobalBuffer: Permission denied for " - "user_id=%d", - user_id); - return ErrorStatus(EPERM); - } - return DeleteGlobalBuffer(key); -} - -pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetGlobalBuffer( - pdx::Message& /* message */, DvrGlobalBufferKey key) { - ALOGD_IF(TRACE, "DisplayService::OnGetGlobalBuffer: key=%d", key); - auto global_buffer = global_buffers_.find(key); - if (global_buffer != global_buffers_.end()) - return {BorrowedNativeBufferHandle(*global_buffer->second, 0)}; - else - return pdx::ErrorStatus(EINVAL); -} - -// Calls the message handler for the DisplaySurface associated with this -// channel. -Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) { - auto surface = std::static_pointer_cast<DisplaySurface>(message.GetChannel()); - ALOGW_IF(!surface, - "DisplayService::HandleSurfaceMessage: surface is nullptr!"); - - if (surface) - return surface->HandleMessage(message); - else - return ErrorStatus(EINVAL); -} - -std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface( - int surface_id) const { - return std::static_pointer_cast<DisplaySurface>(GetChannel(surface_id)); -} - -std::vector<std::shared_ptr<DisplaySurface>> -DisplayService::GetDisplaySurfaces() const { - return GetChannels<DisplaySurface>(); -} - -std::vector<std::shared_ptr<DirectDisplaySurface>> -DisplayService::GetVisibleDisplaySurfaces() const { - std::vector<std::shared_ptr<DirectDisplaySurface>> visible_surfaces; - - ForEachDisplaySurface( - SurfaceType::Direct, - [&](const std::shared_ptr<DisplaySurface>& surface) mutable { - if (surface->visible()) { - visible_surfaces.push_back( - std::static_pointer_cast<DirectDisplaySurface>(surface)); - surface->ClearUpdate(); - } - }); - - return visible_surfaces; -} - -void DisplayService::UpdateActiveDisplaySurfaces() { - auto visible_surfaces = GetVisibleDisplaySurfaces(); - ALOGD_IF(TRACE, - "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces", - visible_surfaces.size()); - hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces)); -} - -pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupGlobalBuffer( - DvrGlobalBufferKey key, size_t size, uint64_t usage) { - auto global_buffer = global_buffers_.find(key); - if (global_buffer == global_buffers_.end()) { - auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1, - HAL_PIXEL_FORMAT_BLOB, usage); - - // Some buffers are used internally. If they were configured with an - // invalid size or format, this will fail. - int result = hardware_composer_.OnNewGlobalBuffer(key, *ion_buffer.get()); - if (result < 0) - return ErrorStatus(result); - global_buffer = - global_buffers_.insert(std::make_pair(key, std::move(ion_buffer))) - .first; - } - - return {BorrowedNativeBufferHandle(*global_buffer->second, 0)}; -} - -pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) { - auto global_buffer = global_buffers_.find(key); - if (global_buffer != global_buffers_.end()) { - // Some buffers are used internally. - hardware_composer_.OnDeletedGlobalBuffer(key); - global_buffers_.erase(global_buffer); - } - - return {0}; -} - -void DisplayService::SetDisplayConfigurationUpdateNotifier( - DisplayConfigurationUpdateNotifier update_notifier) { - update_notifier_ = update_notifier; -} - -void DisplayService::NotifyDisplayConfigurationUpdate() { - if (update_notifier_) - update_notifier_(); -} - -Status<bool> DisplayService::IsVrAppRunning(pdx::Message& /*message*/) { - bool visible = false; - ForEachDisplaySurface( - SurfaceType::Application, - [&visible](const std::shared_ptr<DisplaySurface>& surface) { - if (surface->visible()) - visible = true; - }); - - return {visible}; -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h deleted file mode 100644 index 89f1eaee33..0000000000 --- a/libs/vr/libvrflinger/display_service.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_ - -#include <dvr/dvr_api.h> -#include <pdx/service.h> -#include <pdx/status.h> -#include <private/dvr/bufferhub_rpc.h> -#include <private/dvr/display_protocol.h> - -#include <functional> -#include <iterator> -#include <memory> -#include <string> -#include <vector> - -#include "acquired_buffer.h" -#include "display_surface.h" -#include "epoll_event_dispatcher.h" -#include "hardware_composer.h" - -namespace android { -namespace dvr { - -// DisplayService implements the display service component of VrFlinger. -class DisplayService : public pdx::ServiceBase<DisplayService> { - public: - bool IsInitialized() const override; - std::string DumpState(size_t max_length) override; - - void OnChannelClose(pdx::Message& message, - const std::shared_ptr<pdx::Channel>& channel) override; - pdx::Status<void> HandleMessage(pdx::Message& message) override; - - std::shared_ptr<DisplaySurface> GetDisplaySurface(int surface_id) const; - std::vector<std::shared_ptr<DisplaySurface>> GetDisplaySurfaces() const; - std::vector<std::shared_ptr<DirectDisplaySurface>> GetVisibleDisplaySurfaces() - const; - - // Updates the list of actively displayed surfaces. This must be called after - // any change to client/manager attributes that affect visibility or z order. - void UpdateActiveDisplaySurfaces(); - - pdx::Status<BorrowedNativeBufferHandle> SetupGlobalBuffer( - DvrGlobalBufferKey key, size_t size, uint64_t usage); - - pdx::Status<void> DeleteGlobalBuffer(DvrGlobalBufferKey key); - - template <class A> - void ForEachDisplaySurface(SurfaceType surface_type, A action) const { - ForEachChannel([surface_type, - action](const ChannelIterator::value_type& pair) mutable { - auto surface = std::static_pointer_cast<DisplaySurface>(pair.second); - if (surface->surface_type() == surface_type) - action(surface); - }); - } - - using DisplayConfigurationUpdateNotifier = std::function<void(void)>; - void SetDisplayConfigurationUpdateNotifier( - DisplayConfigurationUpdateNotifier notifier); - - void GrantDisplayOwnership() { hardware_composer_.Enable(); } - void SeizeDisplayOwnership() { hardware_composer_.Disable(); } - void OnBootFinished() { hardware_composer_.OnBootFinished(); } - - private: - friend BASE; - friend DisplaySurface; - - friend class VrDisplayStateService; - - using RequestDisplayCallback = std::function<void(bool)>; - - DisplayService(android::Hwc2::Composer* hidl, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback); - - pdx::Status<BorrowedNativeBufferHandle> OnGetGlobalBuffer( - pdx::Message& message, DvrGlobalBufferKey key); - pdx::Status<display::Metrics> OnGetMetrics(pdx::Message& message); - pdx::Status<std::string> OnGetConfigurationData( - pdx::Message& message, display::ConfigFileType config_type); - pdx::Status<uint8_t> OnGetDisplayIdentificationPort(pdx::Message& message); - pdx::Status<display::SurfaceInfo> OnCreateSurface( - pdx::Message& message, const display::SurfaceAttributes& attributes); - pdx::Status<BorrowedNativeBufferHandle> OnSetupGlobalBuffer( - pdx::Message& message, DvrGlobalBufferKey key, size_t size, - uint64_t usage); - pdx::Status<void> OnDeleteGlobalBuffer(pdx::Message& message, - DvrGlobalBufferKey key); - - // Temporary query for current VR status. Will be removed later. - pdx::Status<bool> IsVrAppRunning(pdx::Message& message); - - pdx::Status<void> AddEventHandler(int fd, int events, - EpollEventDispatcher::Handler handler) { - return dispatcher_.AddEventHandler(fd, events, handler); - } - pdx::Status<void> RemoveEventHandler(int fd) { - return dispatcher_.RemoveEventHandler(fd); - } - - void SurfaceUpdated(SurfaceType surface_type, - display::SurfaceUpdateFlags update_flags); - - // Called by DisplaySurface to signal that a surface property has changed and - // the display manager should be notified. - void NotifyDisplayConfigurationUpdate(); - - pdx::Status<void> HandleSurfaceMessage(pdx::Message& message); - - HardwareComposer hardware_composer_; - EpollEventDispatcher dispatcher_; - DisplayConfigurationUpdateNotifier update_notifier_; - - std::unordered_map<DvrGlobalBufferKey, std::unique_ptr<IonBuffer>> - global_buffers_; - - DisplayService(const DisplayService&) = delete; - void operator=(const DisplayService&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SERVICE_H_ diff --git a/libs/vr/libvrflinger/display_surface.cpp b/libs/vr/libvrflinger/display_surface.cpp deleted file mode 100644 index 87c823e5b9..0000000000 --- a/libs/vr/libvrflinger/display_surface.cpp +++ /dev/null @@ -1,488 +0,0 @@ -#include "display_surface.h" - -#include <private/android_filesystem_config.h> -#include <utils/Trace.h> - -#include <private/dvr/trusted_uids.h> - -#include "display_service.h" -#include "hardware_composer.h" - -#define LOCAL_TRACE 1 - -using android::dvr::display::DisplayProtocol; -using android::pdx::BorrowedChannelHandle; -using android::pdx::ErrorStatus; -using android::pdx::LocalChannelHandle; -using android::pdx::LocalHandle; -using android::pdx::Message; -using android::pdx::RemoteChannelHandle; -using android::pdx::Status; -using android::pdx::rpc::DispatchRemoteMethod; -using android::pdx::rpc::IfAnyOf; - -namespace android { -namespace dvr { - -DisplaySurface::DisplaySurface(DisplayService* service, - SurfaceType surface_type, int surface_id, - int process_id, int user_id) - : service_(service), - surface_type_(surface_type), - surface_id_(surface_id), - process_id_(process_id), - user_id_(user_id), - update_flags_(display::SurfaceUpdateFlags::NewSurface) {} - -DisplaySurface::~DisplaySurface() { - ALOGD_IF(LOCAL_TRACE, - "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d", - surface_id(), process_id()); -} - -Status<void> DisplaySurface::HandleMessage(pdx::Message& message) { - switch (message.GetOp()) { - case DisplayProtocol::SetAttributes::Opcode: - DispatchRemoteMethod<DisplayProtocol::SetAttributes>( - *this, &DisplaySurface::OnSetAttributes, message); - break; - - case DisplayProtocol::GetSurfaceInfo::Opcode: - DispatchRemoteMethod<DisplayProtocol::GetSurfaceInfo>( - *this, &DisplaySurface::OnGetSurfaceInfo, message); - break; - - case DisplayProtocol::CreateQueue::Opcode: - DispatchRemoteMethod<DisplayProtocol::CreateQueue>( - *this, &DisplaySurface::OnCreateQueue, message); - break; - } - - return {}; -} - -Status<void> DisplaySurface::OnSetAttributes( - pdx::Message& /*message*/, const display::SurfaceAttributes& attributes) { - display::SurfaceUpdateFlags update_flags; - - for (const auto& attribute : attributes) { - const auto key = attribute.first; - const auto* variant = &attribute.second; - bool invalid_value = false; - bool visibility_changed = false; - - // Catch attributes that have significance to the display service. - switch (key) { - case display::SurfaceAttribute::ZOrder: - invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call( - variant, [&](const auto& value) { - if (z_order_ != value) { - visibility_changed = true; - z_order_ = value; - } - }); - break; - case display::SurfaceAttribute::Visible: - invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call( - variant, [&](const auto& value) { - if (visible_ != value) { - visibility_changed = true; - visible_ = value; - } - }); - break; - } - - // Only update the attribute map with valid values. This check also has the - // effect of preventing special attributes handled above from being deleted - // by an empty value. - if (invalid_value) { - ALOGW( - "DisplaySurface::OnClientSetAttributes: Failed to set display " - "surface attribute '%d' because of incompatible type: %d", - key, variant->index()); - } else { - // An empty value indicates the attribute should be deleted. - if (variant->empty()) { - auto search = attributes_.find(key); - if (search != attributes_.end()) - attributes_.erase(search); - } else { - attributes_[key] = *variant; - } - - // All attribute changes generate a notification, even if the value - // doesn't change. Visibility attributes set a flag only if the value - // changes. - update_flags.Set(display::SurfaceUpdateFlags::AttributesChanged); - if (visibility_changed) - update_flags.Set(display::SurfaceUpdateFlags::VisibilityChanged); - } - } - - SurfaceUpdated(update_flags); - return {}; -} - -void DisplaySurface::SurfaceUpdated(display::SurfaceUpdateFlags update_flags) { - ALOGD_IF(TRACE, - "DisplaySurface::SurfaceUpdated: surface_id=%d update_flags=0x%x", - surface_id(), update_flags.value()); - - update_flags_.Set(update_flags); - service()->SurfaceUpdated(surface_type(), update_flags_); -} - -void DisplaySurface::ClearUpdate() { - ALOGD_IF(TRACE > 1, "DisplaySurface::ClearUpdate: surface_id=%d", - surface_id()); - update_flags_ = display::SurfaceUpdateFlags::None; -} - -Status<display::SurfaceInfo> DisplaySurface::OnGetSurfaceInfo( - Message& /*message*/) { - ALOGD_IF( - TRACE, - "DisplaySurface::OnGetSurfaceInfo: surface_id=%d visible=%d z_order=%d", - surface_id(), visible(), z_order()); - return {{surface_id(), visible(), z_order()}}; -} - -Status<void> DisplaySurface::RegisterQueue( - const std::shared_ptr<ConsumerQueue>& consumer_queue) { - ALOGD_IF(TRACE, "DisplaySurface::RegisterQueue: surface_id=%d queue_id=%d", - surface_id(), consumer_queue->id()); - // Capture references for the lambda to work around apparent clang bug. - // TODO(eieio): Figure out if there is a clang bug or C++11 ambiguity when - // capturing self and consumer_queue by copy in the following case: - // auto self = Self(); - // [self, consumer_queue](int events) { - // self->OnQueueEvent(consuemr_queue, events); } - // - struct State { - std::shared_ptr<DisplaySurface> surface; - std::shared_ptr<ConsumerQueue> queue; - }; - State state{Self(), consumer_queue}; - - return service()->AddEventHandler( - consumer_queue->queue_fd(), EPOLLIN | EPOLLHUP | EPOLLET, - [state](int events) { - state.surface->OnQueueEvent(state.queue, events); - }); -} - -Status<void> DisplaySurface::UnregisterQueue( - const std::shared_ptr<ConsumerQueue>& consumer_queue) { - ALOGD_IF(TRACE, "DisplaySurface::UnregisterQueue: surface_id=%d queue_id=%d", - surface_id(), consumer_queue->id()); - return service()->RemoveEventHandler(consumer_queue->queue_fd()); -} - -void DisplaySurface::OnQueueEvent( - const std::shared_ptr<ConsumerQueue>& /*consumer_queue*/, int /*events*/) { - ALOGE( - "DisplaySurface::OnQueueEvent: ERROR base virtual method should not be " - "called!!!"); -} - -std::shared_ptr<ConsumerQueue> ApplicationDisplaySurface::GetQueue( - int32_t queue_id) { - ALOGD_IF(TRACE, - "ApplicationDisplaySurface::GetQueue: surface_id=%d queue_id=%d", - surface_id(), queue_id); - - std::lock_guard<std::mutex> autolock(lock_); - auto search = consumer_queues_.find(queue_id); - if (search != consumer_queues_.end()) - return search->second; - else - return nullptr; -} - -std::vector<int32_t> ApplicationDisplaySurface::GetQueueIds() const { - std::lock_guard<std::mutex> autolock(lock_); - std::vector<int32_t> queue_ids; - for (const auto& entry : consumer_queues_) - queue_ids.push_back(entry.first); - return queue_ids; -} - -Status<LocalChannelHandle> ApplicationDisplaySurface::OnCreateQueue( - Message& /*message*/, const ProducerQueueConfig& config) { - ATRACE_NAME("ApplicationDisplaySurface::OnCreateQueue"); - ALOGD_IF(TRACE, - "ApplicationDisplaySurface::OnCreateQueue: surface_id=%d, " - "user_metadata_size=%zu", - surface_id(), config.user_metadata_size); - - std::lock_guard<std::mutex> autolock(lock_); - auto producer = ProducerQueue::Create(config, UsagePolicy{}); - if (!producer) { - ALOGE( - "ApplicationDisplaySurface::OnCreateQueue: Failed to create producer " - "queue!"); - return ErrorStatus(ENOMEM); - } - - std::shared_ptr<ConsumerQueue> consumer = - producer->CreateSilentConsumerQueue(); - auto status = RegisterQueue(consumer); - if (!status) { - ALOGE( - "ApplicationDisplaySurface::OnCreateQueue: Failed to register consumer " - "queue: %s", - status.GetErrorMessage().c_str()); - return status.error_status(); - } - - consumer_queues_[consumer->id()] = std::move(consumer); - - SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged); - return std::move(producer->GetChannelHandle()); -} - -void ApplicationDisplaySurface::OnQueueEvent( - const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) { - ALOGD_IF(TRACE, - "ApplicationDisplaySurface::OnQueueEvent: queue_id=%d events=%x", - consumer_queue->id(), events); - - std::lock_guard<std::mutex> autolock(lock_); - - // Always give the queue a chance to handle its internal bookkeeping. - consumer_queue->HandleQueueEvents(); - - // Check for hangup and remove a queue that is no longer needed. - if (consumer_queue->hung_up()) { - ALOGD_IF(TRACE, "ApplicationDisplaySurface::OnQueueEvent: Removing queue."); - UnregisterQueue(consumer_queue); - auto search = consumer_queues_.find(consumer_queue->id()); - if (search != consumer_queues_.end()) { - consumer_queues_.erase(search); - } else { - ALOGE( - "ApplicationDisplaySurface::OnQueueEvent: Failed to find queue_id=%d", - consumer_queue->id()); - } - SurfaceUpdated(display::SurfaceUpdateFlags::BuffersChanged); - } -} - -std::vector<int32_t> DirectDisplaySurface::GetQueueIds() const { - std::lock_guard<std::mutex> autolock(lock_); - std::vector<int32_t> queue_ids; - if (direct_queue_) - queue_ids.push_back(direct_queue_->id()); - return queue_ids; -} - -Status<LocalChannelHandle> DirectDisplaySurface::OnCreateQueue( - Message& /*message*/, const ProducerQueueConfig& config) { - ATRACE_NAME("DirectDisplaySurface::OnCreateQueue"); - ALOGD_IF(TRACE, - "DirectDisplaySurface::OnCreateQueue: surface_id=%d " - "user_metadata_size=%zu", - surface_id(), config.user_metadata_size); - - std::lock_guard<std::mutex> autolock(lock_); - if (!direct_queue_) { - // Inject the hw composer usage flag to enable the display to read the - // buffers. - auto producer = ProducerQueue::Create( - config, UsagePolicy{GraphicBuffer::USAGE_HW_COMPOSER, 0, 0, 0}); - if (!producer) { - ALOGE( - "DirectDisplaySurface::OnCreateQueue: Failed to create producer " - "queue!"); - return ErrorStatus(ENOMEM); - } - - direct_queue_ = producer->CreateConsumerQueue(); - if (direct_queue_->metadata_size() > 0) { - metadata_.reset(new uint8_t[direct_queue_->metadata_size()]); - } - auto status = RegisterQueue(direct_queue_); - if (!status) { - ALOGE( - "DirectDisplaySurface::OnCreateQueue: Failed to register consumer " - "queue: %s", - status.GetErrorMessage().c_str()); - return status.error_status(); - } - - return std::move(producer->GetChannelHandle()); - } else { - return ErrorStatus(EALREADY); - } -} - -void DirectDisplaySurface::OnQueueEvent( - const std::shared_ptr<ConsumerQueue>& consumer_queue, int events) { - ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: queue_id=%d events=%x", - consumer_queue->id(), events); - - std::lock_guard<std::mutex> autolock(lock_); - - // Always give the queue a chance to handle its internal bookkeeping. - consumer_queue->HandleQueueEvents(); - - // Check for hangup and remove a queue that is no longer needed. - if (consumer_queue->hung_up()) { - ALOGD_IF(TRACE, "DirectDisplaySurface::OnQueueEvent: Removing queue."); - UnregisterQueue(consumer_queue); - direct_queue_ = nullptr; - } -} - -void DirectDisplaySurface::DequeueBuffersLocked() { - if (direct_queue_ == nullptr) { - ALOGE( - "DirectDisplaySurface::DequeueBuffersLocked: Consumer queue is not " - "initialized."); - return; - } - - while (true) { - LocalHandle acquire_fence; - size_t slot; - auto buffer_status = direct_queue_->Dequeue( - 0, &slot, metadata_.get(), - direct_queue_->metadata_size(), &acquire_fence); - ALOGD_IF(TRACE, - "DirectDisplaySurface::DequeueBuffersLocked: Dequeue with metadata_size: %zu", - direct_queue_->metadata_size()); - if (!buffer_status) { - ALOGD_IF( - TRACE > 1 && buffer_status.error() == ETIMEDOUT, - "DirectDisplaySurface::DequeueBuffersLocked: All buffers dequeued."); - ALOGE_IF(buffer_status.error() != ETIMEDOUT, - "DirectDisplaySurface::DequeueBuffersLocked: Failed to dequeue " - "buffer: %s", - buffer_status.GetErrorMessage().c_str()); - return; - } - auto buffer_consumer = buffer_status.take(); - - if (!visible()) { - ATRACE_NAME("DropFrameOnInvisibleSurface"); - ALOGD_IF(TRACE, - "DirectDisplaySurface::DequeueBuffersLocked: Discarding " - "buffer_id=%d on invisible surface.", - buffer_consumer->id()); - buffer_consumer->Discard(); - continue; - } - - if (acquired_buffers_.IsFull()) { - ALOGE( - "DirectDisplaySurface::DequeueBuffersLocked: Posted buffers full, " - "overwriting."); - acquired_buffers_.PopBack(); - } - - acquired_buffers_.Append( - AcquiredBuffer(buffer_consumer, std::move(acquire_fence), slot)); - } -} - -AcquiredBuffer DirectDisplaySurface::AcquireCurrentBuffer() { - std::lock_guard<std::mutex> autolock(lock_); - DequeueBuffersLocked(); - - if (acquired_buffers_.IsEmpty()) { - ALOGE( - "DirectDisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer " - "when none are posted."); - return AcquiredBuffer(); - } - AcquiredBuffer buffer = std::move(acquired_buffers_.Front()); - acquired_buffers_.PopFront(); - ALOGD_IF(TRACE, "DirectDisplaySurface::AcquireCurrentBuffer: buffer_id=%d", - buffer.buffer()->id()); - return buffer; -} - -AcquiredBuffer DirectDisplaySurface::AcquireNewestAvailableBuffer( - AcquiredBuffer* skipped_buffer) { - std::lock_guard<std::mutex> autolock(lock_); - DequeueBuffersLocked(); - - AcquiredBuffer buffer; - int frames = 0; - // Basic latency stopgap for when the application misses a frame: - // If the application recovers on the 2nd or 3rd (etc) frame after - // missing, this code will skip frames to catch up by checking if - // the next frame is also available. - while (!acquired_buffers_.IsEmpty() && - acquired_buffers_.Front().IsAvailable()) { - // Capture the skipped buffer into the result parameter. - // Note that this API only supports skipping one buffer per vsync. - if (frames > 0 && skipped_buffer) - *skipped_buffer = std::move(buffer); - ++frames; - buffer = std::move(acquired_buffers_.Front()); - acquired_buffers_.PopFront(); - if (frames == 2) - break; - } - ALOGD_IF(TRACE, - "DirectDisplaySurface::AcquireNewestAvailableBuffer: buffer_id=%d", - buffer.buffer()->id()); - return buffer; -} - -bool DirectDisplaySurface::IsBufferAvailable() { - std::lock_guard<std::mutex> autolock(lock_); - DequeueBuffersLocked(); - - return !acquired_buffers_.IsEmpty() && - acquired_buffers_.Front().IsAvailable(); -} - -bool DirectDisplaySurface::IsBufferPosted() { - std::lock_guard<std::mutex> autolock(lock_); - DequeueBuffersLocked(); - - return !acquired_buffers_.IsEmpty(); -} - -Status<std::shared_ptr<DisplaySurface>> DisplaySurface::Create( - DisplayService* service, int surface_id, int process_id, int user_id, - const display::SurfaceAttributes& attributes) { - bool direct = false; - auto search = attributes.find(display::SurfaceAttribute::Direct); - if (search != attributes.end()) { - if (!IfAnyOf<int32_t, int64_t, bool, float>::Get(&search->second, - &direct)) { - ALOGE( - "DisplaySurface::Create: Invalid type for SurfaceAttribute::Direct!"); - return ErrorStatus(EINVAL); - } - } - - ALOGD_IF(TRACE, - "DisplaySurface::Create: surface_id=%d process_id=%d user_id=%d " - "direct=%d", - surface_id, process_id, user_id, direct); - - if (direct) { - const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id); - if (trusted) { - return {std::shared_ptr<DisplaySurface>{ - new DirectDisplaySurface(service, surface_id, process_id, user_id)}}; - } else { - ALOGE( - "DisplaySurface::Create: Direct surfaces may only be created by " - "trusted UIDs: user_id=%d", - user_id); - return ErrorStatus(EPERM); - } - } else { - return {std::shared_ptr<DisplaySurface>{new ApplicationDisplaySurface( - service, surface_id, process_id, user_id)}}; - } -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/display_surface.h b/libs/vr/libvrflinger/display_surface.h deleted file mode 100644 index c8b1a078f7..0000000000 --- a/libs/vr/libvrflinger/display_surface.h +++ /dev/null @@ -1,188 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_ - -#include <pdx/file_handle.h> -#include <pdx/service.h> -#include <private/dvr/buffer_hub_queue_client.h> -#include <private/dvr/display_protocol.h> -#include <private/dvr/ring_buffer.h> - -#include <functional> -#include <iterator> -#include <memory> -#include <string> -#include <vector> - -#include "acquired_buffer.h" - -namespace android { -namespace dvr { - -class DisplayService; - -enum class SurfaceType { - Direct, - Application, -}; - -class DisplaySurface : public pdx::Channel { - public: - static pdx::Status<std::shared_ptr<DisplaySurface>> Create( - DisplayService* service, int surface_id, int process_id, int user_id, - const display::SurfaceAttributes& attributes); - - ~DisplaySurface() override; - - DisplayService* service() const { return service_; } - SurfaceType surface_type() const { return surface_type_; } - int surface_id() const { return surface_id_; } - int process_id() const { return process_id_; } - int user_id() const { return user_id_; } - - bool visible() const { return visible_; } - int z_order() const { return z_order_; } - - const display::SurfaceAttributes& attributes() const { return attributes_; } - display::SurfaceUpdateFlags update_flags() const { return update_flags_; } - - virtual std::vector<int32_t> GetQueueIds() const { return {}; } - - bool IsUpdatePending() const { - return update_flags_.value() != display::SurfaceUpdateFlags::None; - } - - protected: - DisplaySurface(DisplayService* service, SurfaceType surface_type, - int surface_id, int process_id, int user_id); - - // Utility to retrieve a shared pointer to this channel as the desired derived - // type. - template < - typename T = DisplaySurface, - typename = std::enable_if_t<std::is_base_of<DisplaySurface, T>::value>> - std::shared_ptr<T> Self() { - return std::static_pointer_cast<T>(shared_from_this()); - } - - virtual pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( - pdx::Message& message, const ProducerQueueConfig& config) = 0; - - // Registers a consumer queue with the event dispatcher in DisplayService. The - // OnQueueEvent callback below is called to handle queue events. - pdx::Status<void> RegisterQueue( - const std::shared_ptr<ConsumerQueue>& consumer_queue); - pdx::Status<void> UnregisterQueue( - const std::shared_ptr<ConsumerQueue>& consumer_queue); - - // Called by the event dispatcher in DisplayService when a registered queue - // event triggers. Executes on the event dispatcher thread. - virtual void OnQueueEvent( - const std::shared_ptr<ConsumerQueue>& consumer_queue, int events); - - void SurfaceUpdated(display::SurfaceUpdateFlags update_flags); - void ClearUpdate(); - - // Synchronizes access to mutable state below between message dispatch thread - // and frame post thread. - mutable std::mutex lock_; - - private: - friend class DisplayService; - friend class DisplayManagerService; - - // Dispatches display surface messages to the appropriate handlers. This - // handler runs on the VrFlinger message dispatch thread. - pdx::Status<void> HandleMessage(pdx::Message& message); - - pdx::Status<void> OnSetAttributes( - pdx::Message& message, const display::SurfaceAttributes& attributes); - pdx::Status<display::SurfaceInfo> OnGetSurfaceInfo(pdx::Message& message); - - DisplayService* service_; - SurfaceType surface_type_; - int surface_id_; - int process_id_; - int user_id_; - - display::SurfaceAttributes attributes_; - display::SurfaceUpdateFlags update_flags_ = display::SurfaceUpdateFlags::None; - - // Subset of attributes that may be interpreted by the display service. - bool visible_ = false; - int z_order_ = 0; - - DisplaySurface(const DisplaySurface&) = delete; - void operator=(const DisplaySurface&) = delete; -}; - -class ApplicationDisplaySurface : public DisplaySurface { - public: - ApplicationDisplaySurface(DisplayService* service, int surface_id, - int process_id, int user_id) - : DisplaySurface(service, SurfaceType::Application, surface_id, - process_id, user_id) {} - - std::shared_ptr<ConsumerQueue> GetQueue(int32_t queue_id); - std::vector<int32_t> GetQueueIds() const override; - - private: - pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( - pdx::Message& message, const ProducerQueueConfig& config) override; - void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue, - int events) override; - - // Accessed by both message dispatch thread and epoll event thread. - std::unordered_map<int32_t, std::shared_ptr<ConsumerQueue>> consumer_queues_; -}; - -class DirectDisplaySurface : public DisplaySurface { - public: - DirectDisplaySurface(DisplayService* service, int surface_id, int process_id, - int user_id) - : DisplaySurface(service, SurfaceType::Direct, surface_id, process_id, - user_id), - acquired_buffers_(kMaxPostedBuffers), - metadata_(nullptr) {} - std::vector<int32_t> GetQueueIds() const override; - bool IsBufferAvailable(); - bool IsBufferPosted(); - AcquiredBuffer AcquireCurrentBuffer(); - - // Get the newest buffer. Up to one buffer will be skipped. If a buffer is - // skipped, it will be stored in skipped_buffer if non null. - AcquiredBuffer AcquireNewestAvailableBuffer(AcquiredBuffer* skipped_buffer); - - private: - pdx::Status<pdx::LocalChannelHandle> OnCreateQueue( - pdx::Message& message, const ProducerQueueConfig& config) override; - void OnQueueEvent(const std::shared_ptr<ConsumerQueue>& consumer_queue, - int events) override; - - // The capacity of the pending buffer queue. Should be enough to hold all the - // buffers of this DisplaySurface, although in practice only 1 or 2 frames - // will be pending at a time. - static constexpr int kSurfaceBufferMaxCount = 4; - static constexpr int kSurfaceViewMaxCount = 4; - static constexpr int kMaxPostedBuffers = - kSurfaceBufferMaxCount * kSurfaceViewMaxCount; - - // Returns whether a frame is available without locking the mutex. - bool IsFrameAvailableNoLock() const; - - // Dequeue all available buffers from the consumer queue. - void DequeueBuffersLocked(); - - // In a triple-buffered surface, up to kMaxPostedBuffers buffers may be - // posted and pending. - RingBuffer<AcquiredBuffer> acquired_buffers_; - - std::shared_ptr<ConsumerQueue> direct_queue_; - - // Stores metadata when it dequeue buffers from consumer queue. - std::unique_ptr<uint8_t[]> metadata_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_DISPLAY_SURFACE_H_ diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp b/libs/vr/libvrflinger/epoll_event_dispatcher.cpp deleted file mode 100644 index 0d5eb8080f..0000000000 --- a/libs/vr/libvrflinger/epoll_event_dispatcher.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "epoll_event_dispatcher.h" - -#include <log/log.h> -#include <sys/epoll.h> -#include <sys/eventfd.h> -#include <sys/prctl.h> - -#include <dvr/performance_client_api.h> - -namespace android { -namespace dvr { - -EpollEventDispatcher::EpollEventDispatcher() { - epoll_fd_.Reset(epoll_create1(EPOLL_CLOEXEC)); - if (!epoll_fd_) { - ALOGE("Failed to create epoll fd: %s", strerror(errno)); - return; - } - - event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - if (!event_fd_) { - ALOGE("Failed to create event for epolling: %s", strerror(errno)); - return; - } - - // Add watch for eventfd. This should only watch for EPOLLIN, which gets set - // when eventfd_write occurs. Use "this" as a unique sentinal value to - // identify events from the event fd. - epoll_event event = {.events = EPOLLIN, .data = {.ptr = this}}; - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, event_fd_.Get(), &event) < 0) { - ALOGE("Failed to add eventfd to epoll set because: %s", strerror(errno)); - return; - } - - thread_ = std::thread(&EpollEventDispatcher::EventThread, this); -} - -EpollEventDispatcher::~EpollEventDispatcher() { Stop(); } - -void EpollEventDispatcher::Stop() { - exit_thread_.store(true); - eventfd_write(event_fd_.Get(), 1); -} - -pdx::Status<void> EpollEventDispatcher::AddEventHandler(int fd, int event_mask, - Handler handler) { - std::lock_guard<std::mutex> lock(lock_); - - epoll_event event; - event.events = event_mask; - event.data.ptr = &(handlers_[fd] = handler); - - ALOGD_IF( - TRACE, - "EpollEventDispatcher::AddEventHandler: fd=%d event_mask=0x%x handler=%p", - fd, event_mask, event.data.ptr); - - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_ADD, fd, &event) < 0) { - const int error = errno; - ALOGE("Failed to add fd to epoll set because: %s", strerror(error)); - return pdx::ErrorStatus(error); - } else { - return {}; - } -} - -pdx::Status<void> EpollEventDispatcher::RemoveEventHandler(int fd) { - ALOGD_IF(TRACE, "EpollEventDispatcher::RemoveEventHandler: fd=%d", fd); - std::lock_guard<std::mutex> lock(lock_); - - epoll_event ee; // See BUGS in man 2 epoll_ctl. - if (epoll_ctl(epoll_fd_.Get(), EPOLL_CTL_DEL, fd, &ee) < 0) { - const int error = errno; - ALOGE("Failed to remove fd from epoll set because: %s", strerror(error)); - return pdx::ErrorStatus(error); - } - - // If the fd was valid above, add it to the list of ids to remove. - removed_handlers_.push_back(fd); - - // Wake up the event thread to clean up. - eventfd_write(event_fd_.Get(), 1); - - return {}; -} - -void EpollEventDispatcher::EventThread() { - prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrEvent"), 0, 0, 0); - - const int error = dvrSetSchedulerClass(0, "graphics"); - LOG_ALWAYS_FATAL_IF( - error < 0, - "EpollEventDispatcher::EventThread: Failed to set scheduler class: %s", - strerror(-error)); - - const size_t kMaxNumEvents = 128; - epoll_event events[kMaxNumEvents]; - - while (!exit_thread_.load()) { - const int num_events = epoll_wait(epoll_fd_.Get(), events, kMaxNumEvents, -1); - if (num_events < 0 && errno != EINTR) - break; - - ALOGD_IF(TRACE > 1, "EpollEventDispatcher::EventThread: num_events=%d", - num_events); - - for (int i = 0; i < num_events; i++) { - ALOGD_IF( - TRACE > 1, - "EpollEventDispatcher::EventThread: event %d: handler=%p events=0x%x", - i, events[i].data.ptr, events[i].events); - - if (events[i].data.ptr == this) { - // Clear pending event on event_fd_. Serialize the read with respect to - // writes from other threads. - std::lock_guard<std::mutex> lock(lock_); - eventfd_t value; - eventfd_read(event_fd_.Get(), &value); - } else { - auto handler = reinterpret_cast<Handler*>(events[i].data.ptr); - if (handler) - (*handler)(events[i].events); - } - } - - // Remove any handlers that have been posted for removal. This is done here - // instead of in RemoveEventHandler() to prevent races between the dispatch - // thread and the code requesting the removal. Handlers are guaranteed to - // stay alive between exiting epoll_wait() and the dispatch loop above. - std::lock_guard<std::mutex> lock(lock_); - for (auto handler_fd : removed_handlers_) { - ALOGD_IF(TRACE, - "EpollEventDispatcher::EventThread: removing handler: fd=%d", - handler_fd); - handlers_.erase(handler_fd); - } - removed_handlers_.clear(); - } -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/epoll_event_dispatcher.h b/libs/vr/libvrflinger/epoll_event_dispatcher.h deleted file mode 100644 index eb687f4e86..0000000000 --- a/libs/vr/libvrflinger/epoll_event_dispatcher.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_ - -#include <sys/epoll.h> - -#include <atomic> -#include <functional> -#include <mutex> -#include <thread> -#include <unordered_map> -#include <vector> - -#include <pdx/file_handle.h> -#include <pdx/status.h> - -namespace android { -namespace dvr { - -class EpollEventDispatcher { - public: - // Function type for event handlers. The handler receives a bitmask of the - // epoll events that occurred on the file descriptor associated with the - // handler. - using Handler = std::function<void(int)>; - - EpollEventDispatcher(); - ~EpollEventDispatcher(); - - // |handler| is called on the internal dispatch thread when |fd| is signaled - // by events in |event_mask|. - pdx::Status<void> AddEventHandler(int fd, int event_mask, Handler handler); - pdx::Status<void> RemoveEventHandler(int fd); - - void Stop(); - - private: - void EventThread(); - - std::thread thread_; - std::atomic<bool> exit_thread_{false}; - - // Protects handlers_ and removed_handlers_ and serializes operations on - // epoll_fd_ and event_fd_. - std::mutex lock_; - - // Maintains a map of fds to event handlers. This is primarily to keep any - // references alive that may be bound in the std::function instances. It is - // not used at dispatch time to avoid performance problems with different - // versions of std::unordered_map. - std::unordered_map<int, Handler> handlers_; - - // List of fds to be removed from the map. The actual removal is performed - // by the event dispatch thread to avoid races. - std::vector<int> removed_handlers_; - - pdx::LocalHandle epoll_fd_; - pdx::LocalHandle event_fd_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_EPOLL_EVENT_DISPATCHER_H_ diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp deleted file mode 100644 index 1f9765b5eb..0000000000 --- a/libs/vr/libvrflinger/hardware_composer.cpp +++ /dev/null @@ -1,1541 +0,0 @@ -#include "hardware_composer.h" - -#include <binder/IServiceManager.h> -#include <cutils/properties.h> -#include <cutils/sched_policy.h> -#include <fcntl.h> -#include <log/log.h> -#include <poll.h> -#include <stdint.h> -#include <sync/sync.h> -#include <sys/eventfd.h> -#include <sys/prctl.h> -#include <sys/resource.h> -#include <sys/system_properties.h> -#include <sys/timerfd.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> -#include <utils/Trace.h> - -#include <algorithm> -#include <chrono> -#include <functional> -#include <map> -#include <sstream> -#include <string> -#include <tuple> - -#include <dvr/dvr_display_types.h> -#include <dvr/performance_client_api.h> -#include <private/dvr/clock_ns.h> -#include <private/dvr/ion_buffer.h> - -using android::hardware::Return; -using android::hardware::Void; -using android::pdx::ErrorStatus; -using android::pdx::LocalHandle; -using android::pdx::Status; -using android::pdx::rpc::EmptyVariant; -using android::pdx::rpc::IfAnyOf; - -using namespace std::chrono_literals; - -namespace android { -namespace dvr { - -namespace { - -const char kDvrPerformanceProperty[] = "sys.dvr.performance"; - -const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns"; - -// Surface flinger uses "VSYNC-sf" and "VSYNC-app" for its version of these -// events. Name ours similarly. -const char kVsyncTraceEventName[] = "VSYNC-vrflinger"; - -// How long to wait after boot finishes before we turn the display off. -constexpr int kBootFinishedDisplayOffTimeoutSec = 10; - -constexpr int kDefaultDisplayWidth = 1920; -constexpr int kDefaultDisplayHeight = 1080; -constexpr int64_t kDefaultVsyncPeriodNs = 16666667; -// Hardware composer reports dpi as dots per thousand inches (dpi * 1000). -constexpr int kDefaultDpi = 400000; - -// Get time offset from a vsync to when the pose for that vsync should be -// predicted out to. For example, if scanout gets halfway through the frame -// at the halfway point between vsyncs, then this could be half the period. -// With global shutter displays, this should be changed to the offset to when -// illumination begins. Low persistence adds a frame of latency, so we predict -// to the center of the next frame. -inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) { - return (vsync_period_ns * 150) / 100; -} - -// Attempts to set the scheduler class and partiton for the current thread. -// Returns true on success or false on failure. -bool SetThreadPolicy(const std::string& scheduler_class, - const std::string& partition) { - int error = dvrSetSchedulerClass(0, scheduler_class.c_str()); - if (error < 0) { - ALOGE( - "SetThreadPolicy: Failed to set scheduler class \"%s\" for " - "thread_id=%d: %s", - scheduler_class.c_str(), gettid(), strerror(-error)); - return false; - } - error = dvrSetCpuPartition(0, partition.c_str()); - if (error < 0) { - ALOGE( - "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: " - "%s", - partition.c_str(), gettid(), strerror(-error)); - return false; - } - return true; -} - -// Utility to generate scoped tracers with arguments. -// TODO(eieio): Move/merge this into utils/Trace.h? -class TraceArgs { - public: - template <typename... Args> - explicit TraceArgs(const char* format, Args&&... args) { - std::array<char, 1024> buffer; - snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...); - atrace_begin(ATRACE_TAG, buffer.data()); - } - - ~TraceArgs() { atrace_end(ATRACE_TAG); } - - private: - TraceArgs(const TraceArgs&) = delete; - void operator=(const TraceArgs&) = delete; -}; - -// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro -// defined in utils/Trace.h. -#define TRACE_FORMAT(format, ...) \ - TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ } - -// Returns "primary" or "external". Useful for writing more readable logs. -const char* GetDisplayName(bool is_primary) { - return is_primary ? "primary" : "external"; -} - -} // anonymous namespace - -HardwareComposer::HardwareComposer() - : initialized_(false), request_display_callback_(nullptr) {} - -HardwareComposer::~HardwareComposer(void) { - UpdatePostThreadState(PostThreadState::Quit, true); - if (post_thread_.joinable()) - post_thread_.join(); - composer_callback_->SetVsyncService(nullptr); -} - -void HardwareComposer::UpdateEdidData(Hwc2::Composer* composer, - hwc2_display_t hw_id) { - const auto error = composer->getDisplayIdentificationData( - hw_id, &display_port_, &display_identification_data_); - if (error != android::hardware::graphics::composer::V2_1::Error::NONE) { - if (error != - android::hardware::graphics::composer::V2_1::Error::UNSUPPORTED) { - ALOGI("hardware_composer: identification data error\n"); - } else { - ALOGI("hardware_composer: identification data unsupported\n"); - } - } -} - -bool HardwareComposer::Initialize( - Hwc2::Composer* composer, hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback) { - if (initialized_) { - ALOGE("HardwareComposer::Initialize: already initialized."); - return false; - } - - request_display_callback_ = request_display_callback; - - primary_display_ = GetDisplayParams(composer, primary_display_id, true); - - vsync_service_ = new VsyncService; - sp<IServiceManager> sm(defaultServiceManager()); - auto result = sm->addService(String16(VsyncService::GetServiceName()), - vsync_service_, false); - LOG_ALWAYS_FATAL_IF(result != android::OK, - "addService(%s) failed", VsyncService::GetServiceName()); - - post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)); - LOG_ALWAYS_FATAL_IF( - !post_thread_event_fd_, - "HardwareComposer: Failed to create interrupt event fd : %s", - strerror(errno)); - - UpdateEdidData(composer, primary_display_id); - - post_thread_ = std::thread(&HardwareComposer::PostThread, this); - - initialized_ = true; - - return initialized_; -} - -void HardwareComposer::Enable() { - UpdatePostThreadState(PostThreadState::Suspended, false); -} - -void HardwareComposer::Disable() { - UpdatePostThreadState(PostThreadState::Suspended, true); - - std::unique_lock<std::mutex> lock(post_thread_mutex_); - post_thread_ready_.wait(lock, [this] { - return !post_thread_resumed_; - }); -} - -void HardwareComposer::OnBootFinished() { - std::lock_guard<std::mutex> lock(post_thread_mutex_); - if (boot_finished_) - return; - boot_finished_ = true; - post_thread_wait_.notify_one(); -} - -// Update the post thread quiescent state based on idle and suspended inputs. -void HardwareComposer::UpdatePostThreadState(PostThreadStateType state, - bool suspend) { - std::unique_lock<std::mutex> lock(post_thread_mutex_); - - // Update the votes in the state variable before evaluating the effective - // quiescent state. Any bits set in post_thread_state_ indicate that the post - // thread should be suspended. - if (suspend) { - post_thread_state_ |= state; - } else { - post_thread_state_ &= ~state; - } - - const bool quit = post_thread_state_ & PostThreadState::Quit; - const bool effective_suspend = post_thread_state_ != PostThreadState::Active; - if (quit) { - post_thread_quiescent_ = true; - eventfd_write(post_thread_event_fd_.Get(), 1); - post_thread_wait_.notify_one(); - } else if (effective_suspend && !post_thread_quiescent_) { - post_thread_quiescent_ = true; - eventfd_write(post_thread_event_fd_.Get(), 1); - } else if (!effective_suspend && post_thread_quiescent_) { - post_thread_quiescent_ = false; - eventfd_t value; - eventfd_read(post_thread_event_fd_.Get(), &value); - post_thread_wait_.notify_one(); - } -} - -void HardwareComposer::CreateComposer() { - if (composer_) - return; - composer_ = Hwc2::Composer::create("default"); - composer_callback_ = new ComposerCallback; - composer_->registerCallback(composer_callback_); - LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(), - "Registered composer callback but didn't get hotplug for primary" - " display"); - composer_callback_->SetVsyncService(vsync_service_); -} - -void HardwareComposer::OnPostThreadResumed() { - ALOGI("OnPostThreadResumed"); - EnableDisplay(*target_display_, true); - - // Trigger target-specific performance mode change. - property_set(kDvrPerformanceProperty, "performance"); -} - -void HardwareComposer::OnPostThreadPaused() { - ALOGI("OnPostThreadPaused"); - retire_fence_fds_.clear(); - layers_.clear(); - - // Phones create a new composer client on resume and destroy it on pause. - if (composer_callback_ != nullptr) { - composer_callback_->SetVsyncService(nullptr); - composer_callback_ = nullptr; - } - composer_.reset(nullptr); - - // Trigger target-specific performance mode change. - property_set(kDvrPerformanceProperty, "idle"); -} - -bool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock, - int timeout_sec, - const std::function<bool()>& pred) { - auto pred_with_quit = [&] { - return pred() || (post_thread_state_ & PostThreadState::Quit); - }; - if (timeout_sec >= 0) { - post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec), - pred_with_quit); - } else { - post_thread_wait_.wait(lock, pred_with_quit); - } - if (post_thread_state_ & PostThreadState::Quit) { - ALOGI("HardwareComposer::PostThread: Quitting."); - return true; - } - return false; -} - -HWC::Error HardwareComposer::Validate(hwc2_display_t display) { - uint32_t num_types; - uint32_t num_requests; - HWC::Error error = - composer_->validateDisplay(display, &num_types, &num_requests); - - if (error == HWC2_ERROR_HAS_CHANGES) { - ALOGE("Hardware composer has requested composition changes, " - "which we don't support."); - // Accept the changes anyway and see if we can get something on the screen. - error = composer_->acceptDisplayChanges(display); - } - - return error; -} - -bool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) { - HWC::Error error = composer_->setVsyncEnabled(display.id, - (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE - : HWC2_VSYNC_DISABLE)); - if (error != HWC::Error::None) { - ALOGE("Error attempting to %s vsync on %s display: %s", - enabled ? "enable" : "disable", GetDisplayName(display.is_primary), - error.to_string().c_str()); - } - return error == HWC::Error::None; -} - -bool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) { - ALOGI("Turning %s display %s", GetDisplayName(display.is_primary), - active ? "on" : "off"); - HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off; - HWC::Error error = composer_->setPowerMode(display.id, - power_mode.cast<Hwc2::IComposerClient::PowerMode>()); - if (error != HWC::Error::None) { - ALOGE("Error attempting to turn %s display %s: %s", - GetDisplayName(display.is_primary), active ? "on" : "off", - error.to_string().c_str()); - } - return error == HWC::Error::None; -} - -bool HardwareComposer::EnableDisplay(const DisplayParams& display, - bool enabled) { - bool power_result; - bool vsync_result; - // When turning a display on, we set the power state then set vsync. When - // turning a display off we do it in the opposite order. - if (enabled) { - power_result = SetPowerMode(display, enabled); - vsync_result = EnableVsync(display, enabled); - } else { - vsync_result = EnableVsync(display, enabled); - power_result = SetPowerMode(display, enabled); - } - return power_result && vsync_result; -} - -HWC::Error HardwareComposer::Present(hwc2_display_t display) { - int32_t present_fence; - HWC::Error error = composer_->presentDisplay(display, &present_fence); - - // According to the documentation, this fence is signaled at the time of - // vsync/DMA for physical displays. - if (error == HWC::Error::None) { - retire_fence_fds_.emplace_back(present_fence); - } else { - ATRACE_INT("HardwareComposer: PresentResult", error); - } - - return error; -} - -DisplayParams HardwareComposer::GetDisplayParams( - Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) { - DisplayParams params; - params.id = display; - params.is_primary = is_primary; - - Hwc2::Config config; - HWC::Error error = composer->getActiveConfig(display, &config); - - if (error == HWC::Error::None) { - auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name) - -> std::optional<int32_t> { - int32_t val; - HWC::Error error = composer->getDisplayAttribute( - display, config, (Hwc2::IComposerClient::Attribute)attr, &val); - if (error != HWC::Error::None) { - ALOGE("Failed to get %s display attr %s: %s", - GetDisplayName(is_primary), attr_name, - error.to_string().c_str()); - return std::nullopt; - } - return val; - }; - - auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width"); - auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height"); - - if (width && height) { - params.width = *width; - params.height = *height; - } else { - ALOGI("Failed to get width and/or height for %s display. Using default" - " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth, - kDefaultDisplayHeight); - params.width = kDefaultDisplayWidth; - params.height = kDefaultDisplayHeight; - } - - auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period"); - if (vsync_period) { - params.vsync_period_ns = *vsync_period; - } else { - ALOGI("Failed to get vsync period for %s display. Using default vsync" - " period %.2fms", GetDisplayName(is_primary), - static_cast<float>(kDefaultVsyncPeriodNs) / 1000000); - params.vsync_period_ns = kDefaultVsyncPeriodNs; - } - - auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X"); - auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y"); - if (dpi_x && dpi_y) { - params.dpi.x = *dpi_x; - params.dpi.y = *dpi_y; - } else { - ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default" - " dpi %d.", GetDisplayName(is_primary), kDefaultDpi); - params.dpi.x = kDefaultDpi; - params.dpi.y = kDefaultDpi; - } - } else { - ALOGE("HardwareComposer: Failed to get current %s display config: %d." - " Using default display values.", - GetDisplayName(is_primary), error.value); - params.width = kDefaultDisplayWidth; - params.height = kDefaultDisplayHeight; - params.dpi.x = kDefaultDpi; - params.dpi.y = kDefaultDpi; - params.vsync_period_ns = kDefaultVsyncPeriodNs; - } - - ALOGI( - "HardwareComposer: %s display attributes: width=%d height=%d " - "vsync_period_ns=%d DPI=%dx%d", - GetDisplayName(is_primary), - params.width, - params.height, - params.vsync_period_ns, - params.dpi.x, - params.dpi.y); - - return params; -} - -std::string HardwareComposer::Dump() { - std::unique_lock<std::mutex> lock(post_thread_mutex_); - std::ostringstream stream; - - auto print_display_metrics = [&](const DisplayParams& params) { - stream << GetDisplayName(params.is_primary) - << " display metrics: " << params.width << "x" - << params.height << " " << (params.dpi.x / 1000.0) - << "x" << (params.dpi.y / 1000.0) << " dpi @ " - << (1000000000.0 / params.vsync_period_ns) << " Hz" - << std::endl; - }; - - print_display_metrics(primary_display_); - if (external_display_) - print_display_metrics(*external_display_); - - stream << "Post thread resumed: " << post_thread_resumed_ << std::endl; - stream << "Active layers: " << layers_.size() << std::endl; - stream << std::endl; - - for (size_t i = 0; i < layers_.size(); i++) { - stream << "Layer " << i << ":"; - stream << " type=" << layers_[i].GetCompositionType().to_string(); - stream << " surface_id=" << layers_[i].GetSurfaceId(); - stream << " buffer_id=" << layers_[i].GetBufferId(); - stream << std::endl; - } - stream << std::endl; - - if (post_thread_resumed_) { - stream << "Hardware Composer Debug Info:" << std::endl; - stream << composer_->dumpDebugInfo(); - } - - return stream.str(); -} - -void HardwareComposer::PostLayers(hwc2_display_t display) { - ATRACE_NAME("HardwareComposer::PostLayers"); - - // Setup the hardware composer layers with current buffers. - for (auto& layer : layers_) { - layer.Prepare(); - } - - // Now that we have taken in a frame from the application, we have a chance - // to drop the frame before passing the frame along to HWC. - // If the display driver has become backed up, we detect it here and then - // react by skipping this frame to catch up latency. - while (!retire_fence_fds_.empty() && - (!retire_fence_fds_.front() || - sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) { - // There are only 2 fences in here, no performance problem to shift the - // array of ints. - retire_fence_fds_.erase(retire_fence_fds_.begin()); - } - - const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) > - post_thread_config_.allowed_pending_fence_count; - - if (is_fence_pending) { - ATRACE_INT("frame_skip_count", ++frame_skip_count_); - - ALOGW_IF(is_fence_pending, - "Warning: dropping a frame to catch up with HWC (pending = %zd)", - retire_fence_fds_.size()); - - for (auto& layer : layers_) { - layer.Drop(); - } - return; - } else { - // Make the transition more obvious in systrace when the frame skip happens - // above. - ATRACE_INT("frame_skip_count", 0); - } - -#if TRACE > 1 - for (size_t i = 0; i < layers_.size(); i++) { - ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s", - i, layers_[i].GetBufferId(), - layers_[i].GetCompositionType().to_string().c_str()); - } -#endif - - HWC::Error error = Validate(display); - if (error != HWC::Error::None) { - ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64, - error.to_string().c_str(), display); - return; - } - - error = Present(display); - if (error != HWC::Error::None) { - ALOGE("HardwareComposer::PostLayers: Present failed: %s", - error.to_string().c_str()); - return; - } - - std::vector<Hwc2::Layer> out_layers; - std::vector<int> out_fences; - error = composer_->getReleaseFences(display, - &out_layers, &out_fences); - ALOGE_IF(error != HWC::Error::None, - "HardwareComposer::PostLayers: Failed to get release fences: %s", - error.to_string().c_str()); - - // Perform post-frame bookkeeping. - uint32_t num_elements = out_layers.size(); - for (size_t i = 0; i < num_elements; ++i) { - for (auto& layer : layers_) { - if (layer.GetLayerHandle() == out_layers[i]) { - layer.Finish(out_fences[i]); - } - } - } -} - -void HardwareComposer::SetDisplaySurfaces( - std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) { - ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd", - surfaces.size()); - const bool display_idle = surfaces.size() == 0; - { - std::unique_lock<std::mutex> lock(post_thread_mutex_); - surfaces_ = std::move(surfaces); - surfaces_changed_ = true; - } - - if (request_display_callback_) - request_display_callback_(!display_idle); - - // Set idle state based on whether there are any surfaces to handle. - UpdatePostThreadState(PostThreadState::Idle, display_idle); -} - -int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key, - IonBuffer& ion_buffer) { - if (key == DvrGlobalBuffers::kVsyncBuffer) { - vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>( - &ion_buffer, CPUUsageMode::WRITE_OFTEN); - - if (vsync_ring_->IsMapped() == false) { - return -EPERM; - } - } - - if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) { - return MapConfigBuffer(ion_buffer); - } - - return 0; -} - -void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) { - if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) { - ConfigBufferDeleted(); - } -} - -int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) { - std::lock_guard<std::mutex> lock(shared_config_mutex_); - shared_config_ring_ = DvrConfigRing(); - - if (ion_buffer.width() < DvrConfigRing::MemorySize()) { - ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size."); - return -EINVAL; - } - - void* buffer_base = 0; - int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(), - ion_buffer.height(), &buffer_base); - if (result != 0) { - ALOGE( - "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config " - "buffer."); - return -EPERM; - } - - shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width()); - ion_buffer.Unlock(); - - return 0; -} - -void HardwareComposer::ConfigBufferDeleted() { - std::lock_guard<std::mutex> lock(shared_config_mutex_); - shared_config_ring_ = DvrConfigRing(); -} - -void HardwareComposer::UpdateConfigBuffer() { - std::lock_guard<std::mutex> lock(shared_config_mutex_); - if (!shared_config_ring_.is_valid()) - return; - // Copy from latest record in shared_config_ring_ to local copy. - DvrConfig record; - if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) { - ALOGI("DvrConfig updated: sequence %u, post offset %d", - shared_config_ring_sequence_, record.frame_post_offset_ns); - ++shared_config_ring_sequence_; - post_thread_config_ = record; - } -} - -int HardwareComposer::PostThreadPollInterruptible( - const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) { - pollfd pfd[2] = { - { - .fd = event_fd.Get(), - .events = static_cast<short>(requested_events), - .revents = 0, - }, - { - .fd = post_thread_event_fd_.Get(), - .events = POLLPRI | POLLIN, - .revents = 0, - }, - }; - int ret, error; - do { - ret = poll(pfd, 2, timeout_ms); - error = errno; - ALOGW_IF(ret < 0, - "HardwareComposer::PostThreadPollInterruptible: Error during " - "poll(): %s (%d)", - strerror(error), error); - } while (ret < 0 && error == EINTR); - - if (ret < 0) { - return -error; - } else if (ret == 0) { - return -ETIMEDOUT; - } else if (pfd[0].revents != 0) { - return 0; - } else if (pfd[1].revents != 0) { - ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents); - return kPostThreadInterrupted; - } else { - return 0; - } -} - -// Sleep until the next predicted vsync, returning the predicted vsync -// timestamp. -Status<int64_t> HardwareComposer::WaitForPredictedVSync() { - const int64_t predicted_vsync_time = last_vsync_timestamp_ + - (target_display_->vsync_period_ns * vsync_prediction_interval_); - const int error = SleepUntil(predicted_vsync_time); - if (error < 0) { - ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s", - strerror(-error)); - return error; - } - return {predicted_vsync_time}; -} - -int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) { - const int timer_fd = vsync_sleep_timer_fd_.Get(); - const itimerspec wakeup_itimerspec = { - .it_interval = {.tv_sec = 0, .tv_nsec = 0}, - .it_value = NsToTimespec(wakeup_timestamp), - }; - int ret = - timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr); - int error = errno; - if (ret < 0) { - ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s", - strerror(error)); - return -error; - } - - return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN, - /*timeout_ms*/ -1); -} - -void HardwareComposer::PostThread() { - // NOLINTNEXTLINE(runtime/int) - prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0); - - // Set the scheduler to SCHED_FIFO with high priority. If this fails here - // there may have been a startup timing issue between this thread and - // performanced. Try again later when this thread becomes active. - bool thread_policy_setup = - SetThreadPolicy("graphics:high", "/system/performance"); - - // Create a timerfd based on CLOCK_MONOTINIC. - vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0)); - LOG_ALWAYS_FATAL_IF( - !vsync_sleep_timer_fd_, - "HardwareComposer: Failed to create vsync sleep timerfd: %s", - strerror(errno)); - - struct VsyncEyeOffsets { int64_t left_ns, right_ns; }; - bool was_running = false; - - auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets { - VsyncEyeOffsets offsets; - offsets.left_ns = - GetPosePredictionTimeOffset(target_display_->vsync_period_ns); - - // TODO(jbates) Query vblank time from device, when such an API is - // available. This value (6.3%) was measured on A00 in low persistence mode. - int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000; - offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2; - - // Check property for overriding right eye offset value. - offsets.right_ns = - property_get_int64(kRightEyeOffsetProperty, offsets.right_ns); - - return offsets; - }; - - VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets(); - - while (1) { - ATRACE_NAME("HardwareComposer::PostThread"); - - // Check for updated config once per vsync. - UpdateConfigBuffer(); - - while (post_thread_quiescent_) { - std::unique_lock<std::mutex> lock(post_thread_mutex_); - ALOGI("HardwareComposer::PostThread: Entering quiescent state."); - - if (was_running) { - vsync_trace_parity_ = false; - ATRACE_INT(kVsyncTraceEventName, 0); - } - - // Tear down resources. - OnPostThreadPaused(); - was_running = false; - post_thread_resumed_ = false; - post_thread_ready_.notify_all(); - - if (PostThreadCondWait(lock, -1, - [this] { return !post_thread_quiescent_; })) { - // A true return value means we've been asked to quit. - return; - } - - post_thread_resumed_ = true; - post_thread_ready_.notify_all(); - - ALOGI("HardwareComposer::PostThread: Exiting quiescent state."); - } - - if (!composer_) - CreateComposer(); - - bool target_display_changed = UpdateTargetDisplay(); - bool just_resumed_running = !was_running; - was_running = true; - - if (target_display_changed) - vsync_eye_offsets = get_vsync_eye_offsets(); - - if (just_resumed_running) { - OnPostThreadResumed(); - - // Try to setup the scheduler policy if it failed during startup. Only - // attempt to do this on transitions from inactive to active to avoid - // spamming the system with RPCs and log messages. - if (!thread_policy_setup) { - thread_policy_setup = - SetThreadPolicy("graphics:high", "/system/performance"); - } - } - - if (target_display_changed || just_resumed_running) { - // Initialize the last vsync timestamp with the current time. The - // predictor below uses this time + the vsync interval in absolute time - // units for the initial delay. Once the driver starts reporting vsync the - // predictor will sync up with the real vsync. - last_vsync_timestamp_ = GetSystemClockNs(); - vsync_prediction_interval_ = 1; - retire_fence_fds_.clear(); - } - - int64_t vsync_timestamp = 0; - { - TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64 - ";prediction_interval=%d|", - vsync_count_ + 1, last_vsync_timestamp_, - vsync_prediction_interval_); - - auto status = WaitForPredictedVSync(); - ALOGE_IF( - !status, - "HardwareComposer::PostThread: Failed to wait for vsync event: %s", - status.GetErrorMessage().c_str()); - - // If there was an error either sleeping was interrupted due to pausing or - // there was an error getting the latest timestamp. - if (!status) - continue; - - // Predicted vsync timestamp for this interval. This is stable because we - // use absolute time for the wakeup timer. - vsync_timestamp = status.get(); - } - - vsync_trace_parity_ = !vsync_trace_parity_; - ATRACE_INT(kVsyncTraceEventName, vsync_trace_parity_ ? 1 : 0); - - // Advance the vsync counter only if the system is keeping up with hardware - // vsync to give clients an indication of the delays. - if (vsync_prediction_interval_ == 1) - ++vsync_count_; - - UpdateLayerConfig(); - - // Publish the vsync event. - if (vsync_ring_) { - DvrVsync vsync; - vsync.vsync_count = vsync_count_; - vsync.vsync_timestamp_ns = vsync_timestamp; - vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns; - vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns; - vsync.vsync_period_ns = target_display_->vsync_period_ns; - - vsync_ring_->Publish(vsync); - } - - { - // Sleep until shortly before vsync. - ATRACE_NAME("sleep"); - - const int64_t display_time_est_ns = - vsync_timestamp + target_display_->vsync_period_ns; - const int64_t now_ns = GetSystemClockNs(); - const int64_t sleep_time_ns = display_time_est_ns - now_ns - - post_thread_config_.frame_post_offset_ns; - const int64_t wakeup_time_ns = - display_time_est_ns - post_thread_config_.frame_post_offset_ns; - - ATRACE_INT64("sleep_time_ns", sleep_time_ns); - if (sleep_time_ns > 0) { - int error = SleepUntil(wakeup_time_ns); - ALOGE_IF(error < 0 && error != kPostThreadInterrupted, - "HardwareComposer::PostThread: Failed to sleep: %s", - strerror(-error)); - // If the sleep was interrupted (error == kPostThreadInterrupted), - // we still go through and present this frame because we may have set - // layers earlier and we want to flush the Composer's internal command - // buffer by continuing through to validate and present. - } - } - - { - auto status = composer_callback_->GetVsyncTime(target_display_->id); - - // If we failed to read vsync there might be a problem with the driver. - // Since there's nothing we can do just behave as though we didn't get an - // updated vsync time and let the prediction continue. - const int64_t current_vsync_timestamp = - status ? status.get() : last_vsync_timestamp_; - - const bool vsync_delayed = - last_vsync_timestamp_ == current_vsync_timestamp; - ATRACE_INT("vsync_delayed", vsync_delayed); - - // If vsync was delayed advance the prediction interval and allow the - // fence logic in PostLayers() to skip the frame. - if (vsync_delayed) { - ALOGW( - "HardwareComposer::PostThread: VSYNC timestamp did not advance " - "since last frame: timestamp=%" PRId64 " prediction_interval=%d", - current_vsync_timestamp, vsync_prediction_interval_); - vsync_prediction_interval_++; - } else { - // We have an updated vsync timestamp, reset the prediction interval. - last_vsync_timestamp_ = current_vsync_timestamp; - vsync_prediction_interval_ = 1; - } - } - - PostLayers(target_display_->id); - } -} - -bool HardwareComposer::UpdateTargetDisplay() { - bool target_display_changed = false; - auto displays = composer_callback_->GetDisplays(); - if (displays.external_display_was_hotplugged) { - bool was_using_external_display = !target_display_->is_primary; - if (was_using_external_display) { - // The external display was hotplugged, so make sure to ignore any bad - // display errors as we destroy the layers. - for (auto& layer: layers_) - layer.IgnoreBadDisplayErrorsOnDestroy(true); - } - - if (displays.external_display) { - // External display was connected - external_display_ = GetDisplayParams(composer_.get(), - *displays.external_display, /*is_primary*/ false); - - ALOGI("External display connected. Switching to external display."); - target_display_ = &(*external_display_); - target_display_changed = true; - } else { - // External display was disconnected - external_display_ = std::nullopt; - if (was_using_external_display) { - ALOGI("External display disconnected. Switching to primary display."); - target_display_ = &primary_display_; - target_display_changed = true; - } - } - } - - if (target_display_changed) { - // If we're switching to the external display, turn the primary display off. - if (!target_display_->is_primary) { - EnableDisplay(primary_display_, false); - } - // If we're switching to the primary display, and the external display is - // still connected, turn the external display off. - else if (target_display_->is_primary && external_display_) { - EnableDisplay(*external_display_, false); - } - - // Update the cached edid data for the current display. - UpdateEdidData(composer_.get(), target_display_->id); - - // Turn the new target display on. - EnableDisplay(*target_display_, true); - - // When we switch displays we need to recreate all the layers, so clear the - // current list, which will trigger layer recreation. - layers_.clear(); - } - - return target_display_changed; -} - -// Checks for changes in the surface stack and updates the layer config to -// accomodate the new stack. -void HardwareComposer::UpdateLayerConfig() { - std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces; - { - std::unique_lock<std::mutex> lock(post_thread_mutex_); - - if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty())) - return; - - surfaces = surfaces_; - surfaces_changed_ = false; - } - - ATRACE_NAME("UpdateLayerConfig_HwLayers"); - - // Sort the new direct surface list by z-order to determine the relative order - // of the surfaces. This relative order is used for the HWC z-order value to - // insulate VrFlinger and HWC z-order semantics from each other. - std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) { - return a->z_order() < b->z_order(); - }); - - // Prepare a new layer stack, pulling in layers from the previous - // layer stack that are still active and updating their attributes. - std::vector<Layer> layers; - size_t layer_index = 0; - for (const auto& surface : surfaces) { - // The bottom layer is opaque, other layers blend. - HWC::BlendMode blending = - layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage; - - // Try to find a layer for this surface in the set of active layers. - auto search = - std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id()); - const bool found = search != layers_.end() && - search->GetSurfaceId() == surface->surface_id(); - if (found) { - // Update the attributes of the layer that may have changed. - search->SetBlending(blending); - search->SetZOrder(layer_index); // Relative z-order. - - // Move the existing layer to the new layer set and remove the empty layer - // object from the current set. - layers.push_back(std::move(*search)); - layers_.erase(search); - } else { - // Insert a layer for the new surface. - layers.emplace_back(composer_.get(), *target_display_, surface, blending, - HWC::Composition::Device, layer_index); - } - - ALOGI_IF( - TRACE, - "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d", - layer_index, layers[layer_index].GetSurfaceId()); - - layer_index++; - } - - // Sort the new layer stack by ascending surface id. - std::sort(layers.begin(), layers.end()); - - // Replace the previous layer set with the new layer set. The destructor of - // the previous set will clean up the remaining Layers that are not moved to - // the new layer set. - layers_ = std::move(layers); - - ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers", - layers_.size()); -} - -std::vector<sp<IVsyncCallback>>::const_iterator -HardwareComposer::VsyncService::FindCallback( - const sp<IVsyncCallback>& callback) const { - sp<IBinder> binder = IInterface::asBinder(callback); - return std::find_if(callbacks_.cbegin(), callbacks_.cend(), - [&](const sp<IVsyncCallback>& callback) { - return IInterface::asBinder(callback) == binder; - }); -} - -status_t HardwareComposer::VsyncService::registerCallback( - const sp<IVsyncCallback> callback) { - std::lock_guard<std::mutex> autolock(mutex_); - if (FindCallback(callback) == callbacks_.cend()) { - callbacks_.push_back(callback); - } - return OK; -} - -status_t HardwareComposer::VsyncService::unregisterCallback( - const sp<IVsyncCallback> callback) { - std::lock_guard<std::mutex> autolock(mutex_); - auto iter = FindCallback(callback); - if (iter != callbacks_.cend()) { - callbacks_.erase(iter); - } - return OK; -} - -void HardwareComposer::VsyncService::OnVsync(int64_t vsync_timestamp) { - ATRACE_NAME("VsyncService::OnVsync"); - std::lock_guard<std::mutex> autolock(mutex_); - for (auto iter = callbacks_.begin(); iter != callbacks_.end();) { - if ((*iter)->onVsync(vsync_timestamp) == android::DEAD_OBJECT) { - iter = callbacks_.erase(iter); - } else { - ++iter; - } - } -} - -Return<void> HardwareComposer::ComposerCallback::onHotplug( - Hwc2::Display display, IComposerCallback::Connection conn) { - std::lock_guard<std::mutex> lock(mutex_); - ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn); - - bool is_primary = !got_first_hotplug_ || display == primary_display_.id; - - // Our first onHotplug callback is always for the primary display. - if (!got_first_hotplug_) { - LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED, - "Initial onHotplug callback should be primary display connected"); - got_first_hotplug_ = true; - } else if (is_primary) { - ALOGE("Ignoring unexpected onHotplug() call for primary display"); - return Void(); - } - - if (conn == IComposerCallback::Connection::CONNECTED) { - if (!is_primary) - external_display_ = DisplayInfo(); - DisplayInfo& display_info = is_primary ? - primary_display_ : *external_display_; - display_info.id = display; - - std::array<char, 1024> buffer; - snprintf(buffer.data(), buffer.size(), - "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display); - if (LocalHandle handle{buffer.data(), O_RDONLY}) { - ALOGI( - "HardwareComposer::ComposerCallback::onHotplug: Driver supports " - "vsync_event node for display %" PRIu64, - display); - display_info.driver_vsync_event_fd = std::move(handle); - } else { - ALOGI( - "HardwareComposer::ComposerCallback::onHotplug: Driver does not " - "support vsync_event node for display %" PRIu64, - display); - } - } else if (conn == IComposerCallback::Connection::DISCONNECTED) { - external_display_ = std::nullopt; - } - - if (!is_primary) - external_display_was_hotplugged_ = true; - - return Void(); -} - -Return<void> HardwareComposer::ComposerCallback::onRefresh( - Hwc2::Display /*display*/) { - return hardware::Void(); -} - -Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display, - int64_t timestamp) { - TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|", - display, timestamp); - std::lock_guard<std::mutex> lock(mutex_); - DisplayInfo* display_info = GetDisplayInfo(display); - if (display_info) { - display_info->callback_vsync_timestamp = timestamp; - } - if (primary_display_.id == display && vsync_service_ != nullptr) { - vsync_service_->OnVsync(timestamp); - } - - return Void(); -} - -Return<void> HardwareComposer::ComposerCallback::onVsync_2_4( - Hwc2::Display /*display*/, int64_t /*timestamp*/, - Hwc2::VsyncPeriodNanos /*vsyncPeriodNanos*/) { - LOG_ALWAYS_FATAL("Unexpected onVsync_2_4 callback"); - return Void(); -} - -Return<void> HardwareComposer::ComposerCallback::onVsyncPeriodTimingChanged( - Hwc2::Display /*display*/, - const Hwc2::VsyncPeriodChangeTimeline& /*updatedTimeline*/) { - LOG_ALWAYS_FATAL("Unexpected onVsyncPeriodTimingChanged callback"); - return Void(); -} - -Return<void> HardwareComposer::ComposerCallback::onSeamlessPossible( - Hwc2::Display /*display*/) { - LOG_ALWAYS_FATAL("Unexpected onSeamlessPossible callback"); - return Void(); -} - -void HardwareComposer::ComposerCallback::SetVsyncService( - const sp<VsyncService>& vsync_service) { - std::lock_guard<std::mutex> lock(mutex_); - vsync_service_ = vsync_service; -} - -HardwareComposer::ComposerCallback::Displays -HardwareComposer::ComposerCallback::GetDisplays() { - std::lock_guard<std::mutex> lock(mutex_); - Displays displays; - displays.primary_display = primary_display_.id; - if (external_display_) - displays.external_display = external_display_->id; - if (external_display_was_hotplugged_) { - external_display_was_hotplugged_ = false; - displays.external_display_was_hotplugged = true; - } - return displays; -} - -Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime( - hwc2_display_t display) { - std::lock_guard<std::mutex> autolock(mutex_); - DisplayInfo* display_info = GetDisplayInfo(display); - if (!display_info) { - ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display); - return ErrorStatus(EINVAL); - } - - // See if the driver supports direct vsync events. - LocalHandle& event_fd = display_info->driver_vsync_event_fd; - if (!event_fd) { - // Fall back to returning the last timestamp returned by the vsync - // callback. - return display_info->callback_vsync_timestamp; - } - - // When the driver supports the vsync_event sysfs node we can use it to - // determine the latest vsync timestamp, even if the HWC callback has been - // delayed. - - // The driver returns data in the form "VSYNC=<timestamp ns>". - std::array<char, 32> data; - data.fill('\0'); - - // Seek back to the beginning of the event file. - int ret = lseek(event_fd.Get(), 0, SEEK_SET); - if (ret < 0) { - const int error = errno; - ALOGE( - "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek " - "vsync event fd: %s", - strerror(error)); - return ErrorStatus(error); - } - - // Read the vsync event timestamp. - ret = read(event_fd.Get(), data.data(), data.size()); - if (ret < 0) { - const int error = errno; - ALOGE_IF(error != EAGAIN, - "HardwareComposer::ComposerCallback::GetVsyncTime: Error " - "while reading timestamp: %s", - strerror(error)); - return ErrorStatus(error); - } - - int64_t timestamp; - ret = sscanf(data.data(), "VSYNC=%" PRIu64, - reinterpret_cast<uint64_t*>(×tamp)); - if (ret < 0) { - const int error = errno; - ALOGE( - "HardwareComposer::ComposerCallback::GetVsyncTime: Error while " - "parsing timestamp: %s", - strerror(error)); - return ErrorStatus(error); - } - - return {timestamp}; -} - -HardwareComposer::ComposerCallback::DisplayInfo* -HardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) { - if (display == primary_display_.id) { - return &primary_display_; - } else if (external_display_ && display == external_display_->id) { - return &(*external_display_); - } - return nullptr; -} - -void Layer::Reset() { - if (hardware_composer_layer_) { - HWC::Error error = - composer_->destroyLayer(display_params_.id, hardware_composer_layer_); - if (error != HWC::Error::None && - (!ignore_bad_display_errors_on_destroy_ || - error != HWC::Error::BadDisplay)) { - ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64 - ". error: %s", display_params_.id, hardware_composer_layer_, - error.to_string().c_str()); - } - hardware_composer_layer_ = 0; - } - - z_order_ = 0; - blending_ = HWC::BlendMode::None; - composition_type_ = HWC::Composition::Invalid; - target_composition_type_ = composition_type_; - source_ = EmptyVariant{}; - acquire_fence_.Close(); - surface_rect_functions_applied_ = false; - pending_visibility_settings_ = true; - cached_buffer_map_.clear(); - ignore_bad_display_errors_on_destroy_ = false; -} - -Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params, - const std::shared_ptr<DirectDisplaySurface>& surface, - HWC::BlendMode blending, HWC::Composition composition_type, - size_t z_order) - : composer_(composer), - display_params_(display_params), - z_order_{z_order}, - blending_{blending}, - target_composition_type_{composition_type}, - source_{SourceSurface{surface}} { - CommonLayerSetup(); -} - -Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params, - const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, - HWC::Composition composition_type, size_t z_order) - : composer_(composer), - display_params_(display_params), - z_order_{z_order}, - blending_{blending}, - target_composition_type_{composition_type}, - source_{SourceBuffer{buffer}} { - CommonLayerSetup(); -} - -Layer::~Layer() { Reset(); } - -Layer::Layer(Layer&& other) noexcept { *this = std::move(other); } - -Layer& Layer::operator=(Layer&& other) noexcept { - if (this != &other) { - Reset(); - using std::swap; - swap(composer_, other.composer_); - swap(display_params_, other.display_params_); - swap(hardware_composer_layer_, other.hardware_composer_layer_); - swap(z_order_, other.z_order_); - swap(blending_, other.blending_); - swap(composition_type_, other.composition_type_); - swap(target_composition_type_, other.target_composition_type_); - swap(source_, other.source_); - swap(acquire_fence_, other.acquire_fence_); - swap(surface_rect_functions_applied_, - other.surface_rect_functions_applied_); - swap(pending_visibility_settings_, other.pending_visibility_settings_); - swap(cached_buffer_map_, other.cached_buffer_map_); - swap(ignore_bad_display_errors_on_destroy_, - other.ignore_bad_display_errors_on_destroy_); - } - return *this; -} - -void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) { - if (source_.is<SourceBuffer>()) - std::get<SourceBuffer>(source_) = {buffer}; -} - -void Layer::SetBlending(HWC::BlendMode blending) { - if (blending_ != blending) { - blending_ = blending; - pending_visibility_settings_ = true; - } -} - -void Layer::SetZOrder(size_t z_order) { - if (z_order_ != z_order) { - z_order_ = z_order; - pending_visibility_settings_ = true; - } -} - -IonBuffer* Layer::GetBuffer() { - struct Visitor { - IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); } - IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); } - IonBuffer* operator()(EmptyVariant) { return nullptr; } - }; - return source_.Visit(Visitor{}); -} - -void Layer::UpdateVisibilitySettings() { - if (pending_visibility_settings_) { - pending_visibility_settings_ = false; - - HWC::Error error; - - error = composer_->setLayerBlendMode( - display_params_.id, hardware_composer_layer_, - blending_.cast<Hwc2::IComposerClient::BlendMode>()); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting layer blend mode: %s", - error.to_string().c_str()); - - error = composer_->setLayerZOrder(display_params_.id, - hardware_composer_layer_, z_order_); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting z_ order: %s", - error.to_string().c_str()); - } -} - -void Layer::UpdateLayerSettings() { - HWC::Error error; - - UpdateVisibilitySettings(); - - // TODO(eieio): Use surface attributes or some other mechanism to control - // the layer display frame. - error = composer_->setLayerDisplayFrame( - display_params_.id, hardware_composer_layer_, - {0, 0, display_params_.width, display_params_.height}); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting layer display frame: %s", - error.to_string().c_str()); - - error = composer_->setLayerVisibleRegion( - display_params_.id, hardware_composer_layer_, - {{0, 0, display_params_.width, display_params_.height}}); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting layer visible region: %s", - error.to_string().c_str()); - - error = composer_->setLayerPlaneAlpha(display_params_.id, - hardware_composer_layer_, 1.0f); - ALOGE_IF(error != HWC::Error::None, - "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s", - error.to_string().c_str()); -} - -void Layer::CommonLayerSetup() { - HWC::Error error = composer_->createLayer(display_params_.id, - &hardware_composer_layer_); - ALOGE_IF(error != HWC::Error::None, - "Layer::CommonLayerSetup: Failed to create layer on primary " - "display: %s", - error.to_string().c_str()); - UpdateLayerSettings(); -} - -bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) { - auto search = cached_buffer_map_.find(slot); - if (search != cached_buffer_map_.end() && search->second == buffer_id) - return true; - - // Assign or update the buffer slot. - if (buffer_id >= 0) - cached_buffer_map_[slot] = buffer_id; - return false; -} - -void Layer::Prepare() { - int right, bottom, id; - sp<GraphicBuffer> handle; - std::size_t slot; - - // Acquire the next buffer according to the type of source. - IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) { - std::tie(right, bottom, id, handle, acquire_fence_, slot) = - source.Acquire(); - }); - - TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot); - - // Update any visibility (blending, z-order) changes that occurred since - // last prepare. - UpdateVisibilitySettings(); - - // When a layer is first setup there may be some time before the first - // buffer arrives. Setup the HWC layer as a solid color to stall for time - // until the first buffer arrives. Once the first buffer arrives there will - // always be a buffer for the frame even if it is old. - if (!handle.get()) { - if (composition_type_ == HWC::Composition::Invalid) { - composition_type_ = HWC::Composition::SolidColor; - composer_->setLayerCompositionType( - display_params_.id, hardware_composer_layer_, - composition_type_.cast<Hwc2::IComposerClient::Composition>()); - Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0}; - composer_->setLayerColor(display_params_.id, hardware_composer_layer_, - layer_color); - } else { - // The composition type is already set. Nothing else to do until a - // buffer arrives. - } - } else { - if (composition_type_ != target_composition_type_) { - composition_type_ = target_composition_type_; - composer_->setLayerCompositionType( - display_params_.id, hardware_composer_layer_, - composition_type_.cast<Hwc2::IComposerClient::Composition>()); - } - - // See if the HWC cache already has this buffer. - const bool cached = CheckAndUpdateCachedBuffer(slot, id); - if (cached) - handle = nullptr; - - HWC::Error error{HWC::Error::None}; - error = - composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_, - slot, handle, acquire_fence_.Get()); - - ALOGE_IF(error != HWC::Error::None, - "Layer::Prepare: Error setting layer buffer: %s", - error.to_string().c_str()); - - if (!surface_rect_functions_applied_) { - const float float_right = right; - const float float_bottom = bottom; - error = composer_->setLayerSourceCrop(display_params_.id, - hardware_composer_layer_, - {0, 0, float_right, float_bottom}); - - ALOGE_IF(error != HWC::Error::None, - "Layer::Prepare: Error setting layer source crop: %s", - error.to_string().c_str()); - - surface_rect_functions_applied_ = true; - } - } -} - -void Layer::Finish(int release_fence_fd) { - IfAnyOf<SourceSurface, SourceBuffer>::Call( - &source_, [release_fence_fd](auto& source) { - source.Finish(LocalHandle(release_fence_fd)); - }); -} - -void Layer::Drop() { acquire_fence_.Close(); } - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h deleted file mode 100644 index bfce10b5b0..0000000000 --- a/libs/vr/libvrflinger/hardware_composer.h +++ /dev/null @@ -1,577 +0,0 @@ -#ifndef ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_ -#define ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_ - -#include <ui/GraphicBuffer.h> -#include "DisplayHardware/ComposerHal.h" -#include "hwc_types.h" - -#include <dvr/dvr_shared_buffers.h> -#include <hardware/gralloc.h> -#include <log/log.h> - -#include <array> -#include <condition_variable> -#include <memory> -#include <mutex> -#include <optional> -#include <thread> -#include <tuple> -#include <vector> - -#include <dvr/dvr_config.h> -#include <dvr/dvr_vsync.h> -#include <pdx/file_handle.h> -#include <pdx/rpc/variant.h> -#include <private/dvr/shared_buffer_helpers.h> -#include <private/dvr/vsync_service.h> - -#include "DisplayHardware/DisplayIdentification.h" -#include "acquired_buffer.h" -#include "display_surface.h" - -// Hardware composer HAL doesn't define HWC_TRANSFORM_NONE as of this writing. -#ifndef HWC_TRANSFORM_NONE -#define HWC_TRANSFORM_NONE static_cast<hwc_transform_t>(0) -#endif - -namespace android { -namespace dvr { - -// Basic display metrics for physical displays. -struct DisplayParams { - hwc2_display_t id; - bool is_primary; - - int width; - int height; - - struct { - int x; - int y; - } dpi; - - int vsync_period_ns; -}; - -// Layer represents the connection between a hardware composer layer and the -// source supplying buffers for the layer's contents. -class Layer { - public: - Layer() = default; - - // Sets up the layer to use a display surface as its content source. The Layer - // automatically handles ACQUIRE/RELEASE phases for the surface's buffer train - // every frame. - // - // |composer| The composer instance. - // |display_params| Info about the display to use. - // |blending| receives HWC_BLENDING_* values. - // |composition_type| receives either HWC_FRAMEBUFFER for most layers or - // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing). - // |index| is the index of this surface in the DirectDisplaySurface array. - Layer(Hwc2::Composer* composer, const DisplayParams& display_params, - const std::shared_ptr<DirectDisplaySurface>& surface, - HWC::BlendMode blending, HWC::Composition composition_type, - size_t z_order); - - // Sets up the layer to use a direct buffer as its content source. No special - // handling of the buffer is performed; responsibility for updating or - // changing the buffer each frame is on the caller. - // - // |composer| The composer instance. - // |display_params| Info about the display to use. - // |blending| receives HWC_BLENDING_* values. - // |composition_type| receives either HWC_FRAMEBUFFER for most layers or - // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing). - Layer(Hwc2::Composer* composer, const DisplayParams& display_params, - const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending, - HWC::Composition composition_type, size_t z_order); - - Layer(Layer&&) noexcept; - Layer& operator=(Layer&&) noexcept; - - ~Layer(); - - // Releases any shared pointers and fence handles held by this instance. - void Reset(); - - // Layers that use a direct IonBuffer should call this each frame to update - // which buffer will be used for the next PostLayers. - void UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer); - - // Sets up the hardware composer layer for the next frame. When the layer is - // associated with a display surface, this method automatically ACQUIRES a new - // buffer if one is available. - void Prepare(); - - // After calling prepare, if this frame is to be dropped instead of passing - // along to the HWC, call Drop to close the contained fence(s). - void Drop(); - - // Performs fence bookkeeping after the frame has been posted to hardware - // composer. - void Finish(int release_fence_fd); - - // Sets the blending for the layer. |blending| receives HWC_BLENDING_* values. - void SetBlending(HWC::BlendMode blending); - - // Sets the z-order of this layer - void SetZOrder(size_t z_order); - - // Gets the current IonBuffer associated with this layer. Ownership of the - // buffer DOES NOT pass to the caller and the pointer is not guaranteed to - // remain valid across calls to Layer::Setup(), Layer::Prepare(), or - // Layer::Reset(). YOU HAVE BEEN WARNED. - IonBuffer* GetBuffer(); - - HWC::Composition GetCompositionType() const { return composition_type_; } - HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; } - bool IsLayerSetup() const { return !source_.empty(); } - - int GetSurfaceId() const { - int surface_id = -1; - pdx::rpc::IfAnyOf<SourceSurface>::Call( - &source_, [&surface_id](const SourceSurface& surface_source) { - surface_id = surface_source.GetSurfaceId(); - }); - return surface_id; - } - - int GetBufferId() const { - int buffer_id = -1; - pdx::rpc::IfAnyOf<SourceSurface>::Call( - &source_, [&buffer_id](const SourceSurface& surface_source) { - buffer_id = surface_source.GetBufferId(); - }); - return buffer_id; - } - - // Compares Layers by surface id. - bool operator<(const Layer& other) const { - return GetSurfaceId() < other.GetSurfaceId(); - } - bool operator<(int surface_id) const { return GetSurfaceId() < surface_id; } - - void IgnoreBadDisplayErrorsOnDestroy(bool ignore) { - ignore_bad_display_errors_on_destroy_ = ignore; - } - - private: - void CommonLayerSetup(); - - // Applies all of the settings to this layer using the hwc functions - void UpdateLayerSettings(); - - // Applies visibility settings that may have changed. - void UpdateVisibilitySettings(); - - // Checks whether the buffer, given by id, is associated with the given slot - // in the HWC buffer cache. If the slot is not associated with the given - // buffer the cache is updated to establish the association and the buffer - // should be sent to HWC using setLayerBuffer. Returns true if the association - // was already established, false if not. A buffer_id of -1 is never - // associated and always returns false. - bool CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id); - - // Composer instance. - Hwc2::Composer* composer_ = nullptr; - - // Parameters of the display to use for this layer. - DisplayParams display_params_; - - // The hardware composer layer and metrics to use during the prepare cycle. - hwc2_layer_t hardware_composer_layer_ = 0; - - // Layer properties used to setup the hardware composer layer during the - // Prepare phase. - size_t z_order_ = 0; - HWC::BlendMode blending_ = HWC::BlendMode::None; - HWC::Composition composition_type_ = HWC::Composition::Invalid; - HWC::Composition target_composition_type_ = HWC::Composition::Device; - - // State when the layer is connected to a surface. Provides the same interface - // as SourceBuffer to simplify internal use by Layer. - struct SourceSurface { - std::shared_ptr<DirectDisplaySurface> surface; - AcquiredBuffer acquired_buffer; - pdx::LocalHandle release_fence; - - explicit SourceSurface(const std::shared_ptr<DirectDisplaySurface>& surface) - : surface(surface) {} - - // Attempts to acquire a new buffer from the surface and return a tuple with - // width, height, buffer handle, and fence. If a new buffer is not available - // the previous buffer is returned or an empty value if no buffer has ever - // been posted. When a new buffer is acquired the previous buffer's release - // fence is passed out automatically. - std::tuple<int, int, int, sp<GraphicBuffer>, pdx::LocalHandle, std::size_t> - Acquire() { - if (surface->IsBufferAvailable()) { - acquired_buffer.Release(std::move(release_fence)); - acquired_buffer = surface->AcquireCurrentBuffer(); - ATRACE_ASYNC_END("BufferPost", acquired_buffer.buffer()->id()); - } - if (!acquired_buffer.IsEmpty()) { - return std::make_tuple( - acquired_buffer.buffer()->width(), - acquired_buffer.buffer()->height(), acquired_buffer.buffer()->id(), - acquired_buffer.buffer()->buffer()->buffer(), - acquired_buffer.ClaimAcquireFence(), acquired_buffer.slot()); - } else { - return std::make_tuple(0, 0, -1, nullptr, pdx::LocalHandle{}, 0); - } - } - - void Finish(pdx::LocalHandle fence) { release_fence = std::move(fence); } - - // Gets a pointer to the current acquired buffer or returns nullptr if there - // isn't one. - IonBuffer* GetBuffer() { - if (acquired_buffer.IsAvailable()) - return acquired_buffer.buffer()->buffer(); - else - return nullptr; - } - - // Returns the surface id of the surface. - int GetSurfaceId() const { return surface->surface_id(); } - - // Returns the buffer id for the current buffer. - int GetBufferId() const { - if (acquired_buffer.IsAvailable()) - return acquired_buffer.buffer()->id(); - else - return -1; - } - }; - - // State when the layer is connected to a buffer. Provides the same interface - // as SourceSurface to simplify internal use by Layer. - struct SourceBuffer { - std::shared_ptr<IonBuffer> buffer; - - std::tuple<int, int, int, sp<GraphicBuffer>, pdx::LocalHandle, std::size_t> - Acquire() { - if (buffer) - return std::make_tuple(buffer->width(), buffer->height(), -1, - buffer->buffer(), pdx::LocalHandle{}, 0); - else - return std::make_tuple(0, 0, -1, nullptr, pdx::LocalHandle{}, 0); - } - - void Finish(pdx::LocalHandle /*fence*/) {} - - IonBuffer* GetBuffer() { return buffer.get(); } - - int GetSurfaceId() const { return -1; } - int GetBufferId() const { return -1; } - }; - - // The underlying hardware composer layer is supplied buffers either from a - // surface buffer train or from a buffer directly. - pdx::rpc::Variant<SourceSurface, SourceBuffer> source_; - - pdx::LocalHandle acquire_fence_; - bool surface_rect_functions_applied_ = false; - bool pending_visibility_settings_ = true; - - // Map of buffer slot assignments that have already been established with HWC: - // slot -> buffer_id. When this map contains a matching slot and buffer_id the - // buffer argument to setLayerBuffer may be nullptr to avoid the cost of - // importing a buffer HWC already knows about. - std::map<std::size_t, int> cached_buffer_map_; - - // When calling destroyLayer() on an external display that's been removed we - // typically get HWC2_ERROR_BAD_DISPLAY errors. If - // ignore_bad_display_errors_on_destroy_ is true, don't log the bad display - // errors, since they're expected. - bool ignore_bad_display_errors_on_destroy_ = false; - - Layer(const Layer&) = delete; - void operator=(const Layer&) = delete; -}; - -// HardwareComposer encapsulates the hardware composer HAL, exposing a -// simplified API to post buffers to the display. -// -// HardwareComposer is accessed by both the vr flinger dispatcher thread and the -// surface flinger main thread, in addition to internally running a separate -// thread for compositing/EDS and posting layers to the HAL. When changing how -// variables are used or adding new state think carefully about which threads -// will access the state and whether it needs to be synchronized. -class HardwareComposer { - public: - using RequestDisplayCallback = std::function<void(bool)>; - - HardwareComposer(); - ~HardwareComposer(); - - bool Initialize(Hwc2::Composer* composer, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback); - - bool IsInitialized() const { return initialized_; } - - // Start the post thread if there's work to do (i.e. visible layers). This - // should only be called from surface flinger's main thread. - void Enable(); - // Pause the post thread, blocking until the post thread has signaled that - // it's paused. This should only be called from surface flinger's main thread. - void Disable(); - - // Called on a binder thread. - void OnBootFinished(); - - std::string Dump(); - - const DisplayParams& GetPrimaryDisplayParams() const { - return primary_display_; - } - - // Sets the display surfaces to compose the hardware layer stack. - void SetDisplaySurfaces( - std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces); - - int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer); - void OnDeletedGlobalBuffer(DvrGlobalBufferKey key); - - // Gets the edid data for the current active display (internal or external) - DisplayIdentificationData GetCurrentDisplayIdentificationData() { - return display_identification_data_; - } - - // Gets the edid port for the current active display (internal or external) - uint8_t GetCurrentDisplayPort() { return display_port_; } - - private: - DisplayParams GetDisplayParams(Hwc2::Composer* composer, - hwc2_display_t display, bool is_primary); - - // Turn display vsync on/off. Returns true on success, false on failure. - bool EnableVsync(const DisplayParams& display, bool enabled); - // Turn display power on/off. Returns true on success, false on failure. - bool SetPowerMode(const DisplayParams& display, bool active); - // Convenience function to turn a display on/off. Turns both power and vsync - // on/off. Returns true on success, false on failure. - bool EnableDisplay(const DisplayParams& display, bool enabled); - - class VsyncService : public BnVsyncService { - public: - status_t registerCallback(const sp<IVsyncCallback> callback) override; - status_t unregisterCallback(const sp<IVsyncCallback> callback) override; - void OnVsync(int64_t vsync_timestamp); - private: - std::vector<sp<IVsyncCallback>>::const_iterator FindCallback( - const sp<IVsyncCallback>& callback) const; - std::mutex mutex_; - std::vector<sp<IVsyncCallback>> callbacks_; - }; - - class ComposerCallback : public Hwc2::IComposerCallback { - public: - ComposerCallback() = default; - hardware::Return<void> onHotplug(Hwc2::Display display, - Connection conn) override; - hardware::Return<void> onRefresh(Hwc2::Display display) override; - hardware::Return<void> onVsync(Hwc2::Display display, - int64_t timestamp) override; - hardware::Return<void> onVsync_2_4( - Hwc2::Display display, int64_t timestamp, - Hwc2::VsyncPeriodNanos vsyncPeriodNanos) override; - hardware::Return<void> onVsyncPeriodTimingChanged( - Hwc2::Display display, - const Hwc2::VsyncPeriodChangeTimeline& updatedTimeline) override; - hardware::Return<void> onSeamlessPossible(Hwc2::Display display) override; - - bool GotFirstHotplug() { return got_first_hotplug_; } - void SetVsyncService(const sp<VsyncService>& vsync_service); - - struct Displays { - hwc2_display_t primary_display = 0; - std::optional<hwc2_display_t> external_display; - bool external_display_was_hotplugged = false; - }; - - Displays GetDisplays(); - pdx::Status<int64_t> GetVsyncTime(hwc2_display_t display); - - private: - struct DisplayInfo { - hwc2_display_t id = 0; - pdx::LocalHandle driver_vsync_event_fd; - int64_t callback_vsync_timestamp{0}; - }; - - DisplayInfo* GetDisplayInfo(hwc2_display_t display); - - std::mutex mutex_; - - bool got_first_hotplug_ = false; - DisplayInfo primary_display_; - std::optional<DisplayInfo> external_display_; - bool external_display_was_hotplugged_ = false; - sp<VsyncService> vsync_service_; - }; - - HWC::Error Validate(hwc2_display_t display); - HWC::Error Present(hwc2_display_t display); - - void PostLayers(hwc2_display_t display); - void PostThread(); - - // The post thread has two controlling states: - // 1. Idle: no work to do (no visible surfaces). - // 2. Suspended: explicitly halted (system is not in VR mode). - // When either #1 or #2 is true then the post thread is quiescent, otherwise - // it is active. - using PostThreadStateType = uint32_t; - struct PostThreadState { - enum : PostThreadStateType { - Active = 0, - Idle = (1 << 0), - Suspended = (1 << 1), - Quit = (1 << 2), - }; - }; - - void UpdatePostThreadState(uint32_t state, bool suspend); - - // Blocks until either event_fd becomes readable, or we're interrupted by a - // control thread, or timeout_ms is reached before any events occur. Any - // errors are returned as negative errno values, with -ETIMEDOUT returned in - // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be - // returned. - int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd, - int requested_events, int timeout_ms); - - // WaitForPredictedVSync and SleepUntil are blocking calls made on the post - // thread that can be interrupted by a control thread. If interrupted, these - // calls return kPostThreadInterrupted. - int ReadWaitPPState(); - pdx::Status<int64_t> WaitForPredictedVSync(); - int SleepUntil(int64_t wakeup_timestamp); - - // Initialize any newly connected displays, and set target_display_ to the - // display we should render to. Returns true if target_display_ - // changed. Called only from the post thread. - bool UpdateTargetDisplay(); - - // Reconfigures the layer stack if the display surfaces changed since the last - // frame. Called only from the post thread. - void UpdateLayerConfig(); - - // Called on the post thread to create the Composer instance. - void CreateComposer(); - - // Called on the post thread when the post thread is resumed. - void OnPostThreadResumed(); - // Called on the post thread when the post thread is paused or quits. - void OnPostThreadPaused(); - - // Use post_thread_wait_ to wait for a specific condition, specified by pred. - // timeout_sec < 0 means wait indefinitely, otherwise it specifies the timeout - // in seconds. - // The lock must be held when this function is called. - // Returns true if the wait was interrupted because the post thread was asked - // to quit. - bool PostThreadCondWait(std::unique_lock<std::mutex>& lock, - int timeout_sec, - const std::function<bool()>& pred); - - // Map the given shared memory buffer to our broadcast ring to track updates - // to the config parameters. - int MapConfigBuffer(IonBuffer& ion_buffer); - void ConfigBufferDeleted(); - // Poll for config udpates. - void UpdateConfigBuffer(); - - bool initialized_; - bool is_standalone_device_; - - std::unique_ptr<Hwc2::Composer> composer_; - sp<ComposerCallback> composer_callback_; - RequestDisplayCallback request_display_callback_; - - DisplayParams primary_display_; - std::optional<DisplayParams> external_display_; - DisplayParams* target_display_ = &primary_display_; - - // The list of surfaces we should draw. Set by the display service when - // DirectSurfaces are added, removed, or change visibility. Written by the - // message dispatch thread and read by the post thread. - std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces_; - // Set to true by the dispatch thread whenever surfaces_ changes. Set to false - // by the post thread when the new list of surfaces is processed. - bool surfaces_changed_ = false; - - std::vector<std::shared_ptr<DirectDisplaySurface>> current_surfaces_; - - // Layer set for handling buffer flow into hardware composer layers. This - // vector must be sorted by surface_id in ascending order. - std::vector<Layer> layers_; - - // The layer posting thread. This thread wakes up a short time before vsync to - // hand buffers to hardware composer. - std::thread post_thread_; - - // Post thread state machine and synchronization primitives. - PostThreadStateType post_thread_state_{PostThreadState::Idle | - PostThreadState::Suspended}; - std::atomic<bool> post_thread_quiescent_{true}; - bool post_thread_resumed_{false}; - pdx::LocalHandle post_thread_event_fd_; - std::mutex post_thread_mutex_; - std::condition_variable post_thread_wait_; - std::condition_variable post_thread_ready_; - - // When boot is finished this will be set to true and the post thread will be - // notified via post_thread_wait_. - bool boot_finished_ = false; - - // VSync sleep timerfd. - pdx::LocalHandle vsync_sleep_timer_fd_; - - // The timestamp of the last vsync. - int64_t last_vsync_timestamp_ = 0; - - // The number of vsync intervals to predict since the last vsync. - int vsync_prediction_interval_ = 1; - - // Vsync count since display on. - uint32_t vsync_count_ = 0; - - // Counter tracking the number of skipped frames. - int frame_skip_count_ = 0; - - // Fd array for tracking retire fences that are returned by hwc. This allows - // us to detect when the display driver begins queuing frames. - std::vector<pdx::LocalHandle> retire_fence_fds_; - - // If we are publishing vsync data, we will put it here. - std::unique_ptr<CPUMappedBroadcastRing<DvrVsyncRing>> vsync_ring_; - - // Broadcast ring for receiving config data from the DisplayManager. - DvrConfigRing shared_config_ring_; - uint32_t shared_config_ring_sequence_{0}; - // Config buffer for reading from the post thread. - DvrConfig post_thread_config_; - std::mutex shared_config_mutex_; - - bool vsync_trace_parity_ = false; - sp<VsyncService> vsync_service_; - - // Edid section. - void UpdateEdidData(Hwc2::Composer* composer, hwc2_display_t hw_id); - DisplayIdentificationData display_identification_data_; - uint8_t display_port_; - - static constexpr int kPostThreadInterrupted = 1; - - HardwareComposer(const HardwareComposer&) = delete; - void operator=(const HardwareComposer&) = delete; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_SERVICES_DISPLAYD_HARDWARE_COMPOSER_H_ diff --git a/libs/vr/libvrflinger/hwc_types.h b/libs/vr/libvrflinger/hwc_types.h deleted file mode 100644 index 8b5c3b3e79..0000000000 --- a/libs/vr/libvrflinger/hwc_types.h +++ /dev/null @@ -1,307 +0,0 @@ -#ifndef ANDROID_LIBVRFLINGER_HWCTYPES_H -#define ANDROID_LIBVRFLINGER_HWCTYPES_H - -// General HWC type support. Hardware composer type support is a bit of a mess -// between HWC1, HWC2 C/C++11, and HIDL types. Particularly bothersome is the -// use of enum classes, which make analogous types between versions much -// harder to deal with in a uniform way. -// -// These utilities help address some of these pains by providing a type-safe, -// flexible interface to translate between different type spaces. - -#define HWC2_INCLUDE_STRINGIFICATION -#define HWC2_USE_CPP11 -#include <hardware/hwcomposer2.h> -#undef HWC2_INCLUDE_STRINGIFICATION -#undef HWC2_USE_CPP11 - -#include <string> -#include <type_traits> - -namespace HWC { - -// Value types derived from HWC HAL types. Some of these are stand-alone, -// while others are also wrapped in translator classes below. -using ColorMode = int32_t; // android_color_mode_t; -using Config = hwc2_config_t; -using ColorTransform = - std::underlying_type<android_color_transform_t>::type; // int32_t; -using Dataspace = std::underlying_type<android_dataspace_t>::type; // int32_t; -using DisplayId = hwc2_display_t; -using DisplayRequest = std::underlying_type<HWC2::DisplayRequest>::type; -using Hdr = std::underlying_type<android_hdr_t>::type; // int32_t; -using Layer = hwc2_layer_t; -using PixelFormat = - std::underlying_type<android_pixel_format_t>::type; // int32_t; - -// Type traits and casting utilities. - -// SFINAE utility to evaluate type expressions. -template <typename...> -using TestTypeExpression = void; - -// Traits type to determine the underlying type of an enum, integer, -// or wrapper class. -template <typename T, typename = typename std::is_enum<T>::type, - typename = typename std::is_integral<T>::type, typename = void> -struct UnderlyingType { - using Type = T; -}; -// Partial specialization that matches enum types. Captures the underlying type -// of the enum in member type Type. -template <typename T> -struct UnderlyingType<T, std::true_type, std::false_type> { - using Type = typename std::underlying_type<T>::type; -}; -// Partial specialization that matches integral types. Captures the type of the -// integer in member type Type. -template <typename T> -struct UnderlyingType<T, std::false_type, std::true_type> { - using Type = T; -}; -// Partial specialization that matches the wrapper types below. Captures -// wrapper member type ValueType in member type Type. -template <typename T> -struct UnderlyingType<T, std::false_type, std::false_type, - TestTypeExpression<typename T::ValueType>> { - using Type = typename T::ValueType; -}; - -// Enable if T is an enum with underlying type U. -template <typename T, typename U, typename ReturnType = void> -using EnableIfMatchingEnum = typename std::enable_if< - std::is_enum<T>::value && - std::is_same<U, typename UnderlyingType<T>::Type>::value, - ReturnType>::type; - -// Enable if T and U are the same size/alignment and have the same underlying -// type. Handles enum, integral, and wrapper classes below. -template <typename T, typename U, typename Return = void> -using EnableIfSafeCast = typename std::enable_if< - sizeof(T) == sizeof(U) && alignof(T) == alignof(U) && - std::is_same<typename UnderlyingType<T>::Type, - typename UnderlyingType<U>::Type>::value, - Return>::type; - -// Safely cast between std::vectors of matching enum/integer/wraper types. -// Normally this is not possible with pendantic compiler type checks. However, -// given the same size, alignment, and underlying type this is safe due to -// allocator requirements and array-like element access guarantees. -template <typename T, typename U> -EnableIfSafeCast<T, U, std::vector<T>*> VectorCast(std::vector<U>* in) { - return reinterpret_cast<std::vector<T>*>(in); -} - -// Translator classes that wrap specific HWC types to make translating -// between different types (especially enum class) in code cleaner. - -// Base type for the enum wrappers below. This type provides type definitions -// and implicit conversion logic common to each wrapper type. -template <typename EnumType> -struct Wrapper { - // Alias type of this instantiantion of Wrapper. Useful for inheriting - // constructors in subclasses via "using Base::Base;" statements. - using Base = Wrapper<EnumType>; - - // The enum type wrapped by this instantiation of Wrapper. - using BaseType = EnumType; - - // The underlying type of the base enum type. - using ValueType = typename UnderlyingType<BaseType>::Type; - - // A default constructor is not defined here. Subclasses should define one - // as appropriate to define the correct inital value for the enum type. - - // Default copy constructor. - Wrapper(const Wrapper&) = default; - - // Implicit conversion from ValueType. - // NOLINTNEXTLINE(google-explicit-constructor) - Wrapper(ValueType value) : value(value) {} - - // Implicit conversion from BaseType. - // NOLINTNEXTLINE(google-explicit-constructor) - Wrapper(BaseType value) : value(static_cast<ValueType>(value)) {} - - // Implicit conversion from an enum type of the same underlying type. - template <typename T, typename = EnableIfMatchingEnum<T, ValueType>> - // NOLINTNEXTLINE(google-explicit-constructor) - Wrapper(const T& value) : value(static_cast<ValueType>(value)) {} - - // Implicit conversion to BaseType. - // NOLINTNEXTLINE(google-explicit-constructor) - operator BaseType() const { return static_cast<BaseType>(value); } - - // Implicit conversion to ValueType. - // NOLINTNEXTLINE(google-explicit-constructor) - operator ValueType() const { return value; } - - template <typename T, typename = EnableIfMatchingEnum<T, ValueType>> - T cast() const { - return static_cast<T>(value); - } - - // Converts to string using HWC2 stringification of BaseType. - std::string to_string() const { - return HWC2::to_string(static_cast<BaseType>(value)); - } - - bool operator!=(const Wrapper& other) const { return value != other.value; } - bool operator!=(ValueType other_value) const { return value != other_value; } - bool operator!=(BaseType other_value) const { - return static_cast<BaseType>(value) != other_value; - } - bool operator==(const Wrapper& other) const { return value == other.value; } - bool operator==(ValueType other_value) const { return value == other_value; } - bool operator==(BaseType other_value) const { - return static_cast<BaseType>(value) == other_value; - } - - ValueType value; -}; - -struct Attribute final : public Wrapper<HWC2::Attribute> { - enum : ValueType { - Invalid = HWC2_ATTRIBUTE_INVALID, - Width = HWC2_ATTRIBUTE_WIDTH, - Height = HWC2_ATTRIBUTE_HEIGHT, - VsyncPeriod = HWC2_ATTRIBUTE_VSYNC_PERIOD, - DpiX = HWC2_ATTRIBUTE_DPI_X, - DpiY = HWC2_ATTRIBUTE_DPI_Y, - }; - - Attribute() : Base(Invalid) {} - using Base::Base; -}; - -struct BlendMode final : public Wrapper<HWC2::BlendMode> { - enum : ValueType { - Invalid = HWC2_BLEND_MODE_INVALID, - None = HWC2_BLEND_MODE_NONE, - Premultiplied = HWC2_BLEND_MODE_PREMULTIPLIED, - Coverage = HWC2_BLEND_MODE_COVERAGE, - }; - - BlendMode() : Base(Invalid) {} - using Base::Base; -}; - -struct Composition final : public Wrapper<HWC2::Composition> { - enum : ValueType { - Invalid = HWC2_COMPOSITION_INVALID, - Client = HWC2_COMPOSITION_CLIENT, - Device = HWC2_COMPOSITION_DEVICE, - SolidColor = HWC2_COMPOSITION_SOLID_COLOR, - Cursor = HWC2_COMPOSITION_CURSOR, - Sideband = HWC2_COMPOSITION_SIDEBAND, - }; - - Composition() : Base(Invalid) {} - using Base::Base; -}; - -struct DisplayType final : public Wrapper<HWC2::DisplayType> { - enum : ValueType { - Invalid = HWC2_DISPLAY_TYPE_INVALID, - Physical = HWC2_DISPLAY_TYPE_PHYSICAL, - Virtual = HWC2_DISPLAY_TYPE_VIRTUAL, - }; - - DisplayType() : Base(Invalid) {} - using Base::Base; -}; - -struct Error final : public Wrapper<HWC2::Error> { - enum : ValueType { - None = HWC2_ERROR_NONE, - BadConfig = HWC2_ERROR_BAD_CONFIG, - BadDisplay = HWC2_ERROR_BAD_DISPLAY, - BadLayer = HWC2_ERROR_BAD_LAYER, - BadParameter = HWC2_ERROR_BAD_PARAMETER, - HasChanges = HWC2_ERROR_HAS_CHANGES, - NoResources = HWC2_ERROR_NO_RESOURCES, - NotValidated = HWC2_ERROR_NOT_VALIDATED, - Unsupported = HWC2_ERROR_UNSUPPORTED, - }; - - Error() : Base(None) {} - using Base::Base; -}; - -struct LayerRequest final : public Wrapper<HWC2::LayerRequest> { - enum : ValueType { - ClearClientTarget = HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET, - }; - - LayerRequest() : Base(0) {} - using Base::Base; -}; - -struct PowerMode final : public Wrapper<HWC2::PowerMode> { - enum : ValueType { - Off = HWC2_POWER_MODE_OFF, - DozeSuspend = HWC2_POWER_MODE_DOZE_SUSPEND, - Doze = HWC2_POWER_MODE_DOZE, - On = HWC2_POWER_MODE_ON, - }; - - PowerMode() : Base(Off) {} - using Base::Base; -}; - -struct Transform final : public Wrapper<HWC2::Transform> { - enum : ValueType { - None = 0, - FlipH = HWC_TRANSFORM_FLIP_H, - FlipV = HWC_TRANSFORM_FLIP_V, - Rotate90 = HWC_TRANSFORM_ROT_90, - Rotate180 = HWC_TRANSFORM_ROT_180, - Rotate270 = HWC_TRANSFORM_ROT_270, - FlipHRotate90 = HWC_TRANSFORM_FLIP_H_ROT_90, - FlipVRotate90 = HWC_TRANSFORM_FLIP_V_ROT_90, - }; - - Transform() : Base(None) {} - using Base::Base; -}; - -struct Vsync final : public Wrapper<HWC2::Vsync> { - enum : ValueType { - Invalid = HWC2_VSYNC_INVALID, - Enable = HWC2_VSYNC_ENABLE, - Disable = HWC2_VSYNC_DISABLE, - }; - - Vsync() : Base(Invalid) {} - using Base::Base; -}; - -// Utility color type. -struct Color final { - Color(const Color&) = default; - Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) {} - // NOLINTNEXTLINE(google-explicit-constructor) - Color(hwc_color_t color) : r(color.r), g(color.g), b(color.b), a(color.a) {} - - // NOLINTNEXTLINE(google-explicit-constructor) - operator hwc_color_t() const { return {r, g, b, a}; } - - uint8_t r __attribute__((aligned(1))); - uint8_t g __attribute__((aligned(1))); - uint8_t b __attribute__((aligned(1))); - uint8_t a __attribute__((aligned(1))); -}; - -// Utility rectangle type. -struct Rect final { - // TODO(eieio): Implicit conversion to/from Android rect types. - - int32_t left __attribute__((aligned(4))); - int32_t top __attribute__((aligned(4))); - int32_t right __attribute__((aligned(4))); - int32_t bottom __attribute__((aligned(4))); -}; - -} // namespace HWC - -#endif // ANDROID_LIBVRFLINGER_HWCTYPES_H diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h deleted file mode 100644 index ae52076f99..0000000000 --- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef ANDROID_DVR_VR_FLINGER_H_ -#define ANDROID_DVR_VR_FLINGER_H_ - -#include <thread> -#include <memory> - -#define HWC2_INCLUDE_STRINGIFICATION -#define HWC2_USE_CPP11 -#include <hardware/hwcomposer2.h> -#undef HWC2_INCLUDE_STRINGIFICATION -#undef HWC2_USE_CPP11 - -#include <pdx/service_dispatcher.h> -#include <vr/vr_manager/vr_manager.h> - -namespace android { - -namespace Hwc2 { -class Composer; -} // namespace Hwc2 - -namespace dvr { - -class DisplayService; - -class VrFlinger { - public: - using RequestDisplayCallback = std::function<void(bool)>; - static std::unique_ptr<VrFlinger> Create( - Hwc2::Composer* hidl, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback); - ~VrFlinger(); - - // These functions are all called on surface flinger's main thread. - void OnBootFinished(); - void GrantDisplayOwnership(); - void SeizeDisplayOwnership(); - - // dump all vr flinger state. - std::string Dump(); - - private: - VrFlinger(); - bool Init(Hwc2::Composer* hidl, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback); - - // Needs to be a separate class for binder's ref counting - class PersistentVrStateCallback : public BnPersistentVrStateCallbacks { - public: - explicit PersistentVrStateCallback( - RequestDisplayCallback request_display_callback) - : request_display_callback_(request_display_callback) {} - void onPersistentVrStateChanged(bool enabled) override; - private: - RequestDisplayCallback request_display_callback_; - }; - - std::thread dispatcher_thread_; - std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher_; - std::shared_ptr<android::dvr::DisplayService> display_service_; - sp<PersistentVrStateCallback> persistent_vr_state_callback_; - RequestDisplayCallback request_display_callback_; -}; - -} // namespace dvr -} // namespace android - -#endif // ANDROID_DVR_VR_FLINGER_H_ diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp deleted file mode 100644 index 095f556609..0000000000 --- a/libs/vr/libvrflinger/tests/Android.bp +++ /dev/null @@ -1,47 +0,0 @@ -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "frameworks_native_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["frameworks_native_license"], -} - -shared_libs = [ - "android.hardware.configstore-utils", - "android.hardware.configstore@1.0", - "libbinder", - "libbufferhubqueue", - "libcutils", - "libgui", - "libhidlbase", - "liblog", - "libui", - "libutils", - "libnativewindow", - "libpdx_default_transport", - "libSurfaceFlingerProp", -] - -static_libs = [ - "libdisplay", -] - -cc_test { - srcs: ["vrflinger_test.cpp"], - // See go/apct-presubmit for documentation on how this .filter file is used - // by Android's automated testing infrastructure for test filtering. - data: ["vrflinger_test.filter"], - static_libs: static_libs, - shared_libs: shared_libs, - cflags: [ - "-DLOG_TAG=\"VrFlingerTest\"", - "-DTRACE=0", - "-O0", - "-g", - "-Wall", - "-Werror", - ], - header_libs: ["libsurfaceflinger_headers"], - name: "vrflinger_test", -} diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp deleted file mode 100644 index ac44f74151..0000000000 --- a/libs/vr/libvrflinger/tests/vrflinger_test.cpp +++ /dev/null @@ -1,226 +0,0 @@ -#include <SurfaceFlingerProperties.h> -#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> -#include <android/hardware/configstore/1.1/types.h> -#include <android/hardware_buffer.h> -#include <binder/IServiceManager.h> -#include <binder/Parcel.h> -#include <binder/ProcessState.h> -#include <configstore/Utils.h> -#include <cutils/properties.h> -#include <gtest/gtest.h> -#include <gui/ISurfaceComposer.h> -#include <log/log.h> -#include <utils/StrongPointer.h> - -#include <chrono> -#include <memory> -#include <mutex> -#include <optional> -#include <thread> - -#include <private/dvr/display_client.h> - -using namespace android::hardware::configstore; -using namespace android::hardware::configstore::V1_0; -using android::dvr::display::DisplayClient; -using android::dvr::display::Surface; -using android::dvr::display::SurfaceAttribute; -using android::dvr::display::SurfaceAttributeValue; - -namespace android { -namespace dvr { - -// The transaction code for asking surface flinger if vr flinger is active. This -// is done as a hidden api since it's only used for tests. See the "case 1028" -// block in SurfaceFlinger::onTransact() in SurfaceFlinger.cpp. -constexpr uint32_t kIsVrFlingerActiveTransactionCode = 1028; - -// The maximum amount of time to give vr flinger to activate/deactivate. If the -// switch hasn't completed in this amount of time, the test will fail. -constexpr auto kVrFlingerSwitchMaxTime = std::chrono::seconds(1); - -// How long to wait between each check to see if the vr flinger switch -// completed. -constexpr auto kVrFlingerSwitchPollInterval = std::chrono::milliseconds(50); - -// A Binder connection to surface flinger. -class SurfaceFlingerConnection { - public: - static std::unique_ptr<SurfaceFlingerConnection> Create() { - sp<ISurfaceComposer> surface_flinger = interface_cast<ISurfaceComposer>( - defaultServiceManager()->getService(String16("SurfaceFlinger"))); - if (surface_flinger == nullptr) { - return nullptr; - } - - return std::unique_ptr<SurfaceFlingerConnection>( - new SurfaceFlingerConnection(surface_flinger)); - } - - // Returns true if the surface flinger process is still running. We use this - // to detect if surface flinger has crashed. - bool IsAlive() { - IInterface::asBinder(surface_flinger_)->pingBinder(); - return IInterface::asBinder(surface_flinger_)->isBinderAlive(); - } - - // Return true if vr flinger is currently active, false otherwise. If there's - // an error communicating with surface flinger, std::nullopt is returned. - std::optional<bool> IsVrFlingerActive() { - Parcel data, reply; - status_t result = - data.writeInterfaceToken(surface_flinger_->getInterfaceDescriptor()); - if (result != OK) { - return std::nullopt; - } - result = IInterface::asBinder(surface_flinger_) - ->transact(kIsVrFlingerActiveTransactionCode, data, &reply); - if (result != OK) { - return std::nullopt; - } - bool vr_flinger_active; - result = reply.readBool(&vr_flinger_active); - if (result != OK) { - return std::nullopt; - } - return vr_flinger_active; - } - - enum class VrFlingerSwitchResult : int8_t { - kSuccess, - kTimedOut, - kCommunicationError, - kSurfaceFlingerDied - }; - - // Wait for vr flinger to become active or inactive. - VrFlingerSwitchResult WaitForVrFlinger(bool wait_active) { - return WaitForVrFlingerTimed(wait_active, kVrFlingerSwitchPollInterval, - kVrFlingerSwitchMaxTime); - } - - // Wait for vr flinger to become active or inactive, specifying custom timeouts. - VrFlingerSwitchResult WaitForVrFlingerTimed(bool wait_active, - std::chrono::milliseconds pollInterval, std::chrono::seconds timeout) { - auto start_time = std::chrono::steady_clock::now(); - while (1) { - std::this_thread::sleep_for(pollInterval); - if (!IsAlive()) { - return VrFlingerSwitchResult::kSurfaceFlingerDied; - } - std::optional<bool> vr_flinger_active = IsVrFlingerActive(); - if (!vr_flinger_active.has_value()) { - return VrFlingerSwitchResult::kCommunicationError; - } - if (vr_flinger_active.value() == wait_active) { - return VrFlingerSwitchResult::kSuccess; - } else if (std::chrono::steady_clock::now() - start_time > timeout) { - return VrFlingerSwitchResult::kTimedOut; - } - } - } - - private: - SurfaceFlingerConnection(sp<ISurfaceComposer> surface_flinger) - : surface_flinger_(surface_flinger) {} - - sp<ISurfaceComposer> surface_flinger_ = nullptr; -}; - -// This test activates vr flinger by creating a vr flinger surface, then -// deactivates vr flinger by destroying the surface. We verify that vr flinger -// is activated and deactivated as expected, and that surface flinger doesn't -// crash. -// -// If the device doesn't support vr flinger (as repoted by ConfigStore), the -// test does nothing. -// -// If the device is a standalone vr device, the test also does nothing, since -// this test verifies the behavior of display handoff from surface flinger to vr -// flinger and back, and standalone devices never hand control of the display -// back to surface flinger. -TEST(VrFlingerTest, ActivateDeactivate) { - android::ProcessState::self()->startThreadPool(); - - // Exit immediately if the device doesn't support vr flinger. This ConfigStore - // check is the same mechanism used by surface flinger to decide if it should - // initialize vr flinger. - bool vr_flinger_enabled = android::sysprop::use_vr_flinger(false); - if (!vr_flinger_enabled) { - return; - } - - auto surface_flinger_connection = SurfaceFlingerConnection::Create(); - ASSERT_NE(surface_flinger_connection, nullptr); - - // Verify we start off with vr flinger disabled. - ASSERT_TRUE(surface_flinger_connection->IsAlive()); - auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive(); - ASSERT_TRUE(vr_flinger_active.has_value()); - ASSERT_FALSE(vr_flinger_active.value()); - - // Create a vr flinger surface, and verify vr flinger becomes active. - // Introduce a scope so that, at the end of the scope, the vr flinger surface - // is destroyed, and vr flinger deactivates. - { - auto display_client = DisplayClient::Create(); - ASSERT_NE(display_client, nullptr); - auto metrics = display_client->GetDisplayMetrics(); - ASSERT_TRUE(metrics.ok()); - - auto surface = Surface::CreateSurface({ - {SurfaceAttribute::Direct, SurfaceAttributeValue(true)}, - {SurfaceAttribute::Visible, SurfaceAttributeValue(true)}, - }); - ASSERT_TRUE(surface.ok()); - ASSERT_TRUE(surface.get() != nullptr); - - auto queue = surface.get()->CreateQueue( - metrics.get().display_width, metrics.get().display_height, - /*layer_count=*/1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, - AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | - AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | - AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, - /*capacity=*/1, - /*metadata_size=*/0); - ASSERT_TRUE(queue.ok()); - ASSERT_TRUE(queue.get() != nullptr); - - size_t slot; - pdx::LocalHandle release_fence; - auto buffer = queue.get()->Dequeue(/*timeout=*/0, &slot, &release_fence); - ASSERT_TRUE(buffer.ok()); - ASSERT_TRUE(buffer.get() != nullptr); - - ASSERT_EQ(buffer.get()->width(), metrics.get().display_width); - ASSERT_EQ(buffer.get()->height(), metrics.get().display_height); - - void* raw_buf = nullptr; - ASSERT_GE(buffer.get()->buffer()->Lock( - AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, /*x=*/0, /*y=*/0, - buffer.get()->width(), buffer.get()->height(), &raw_buf), - 0); - ASSERT_NE(raw_buf, nullptr); - uint32_t* pixels = static_cast<uint32_t*>(raw_buf); - - for (int i = 0; i < buffer.get()->stride() * buffer.get()->height(); ++i) { - pixels[i] = 0x0000ff00; - } - - ASSERT_GE(buffer.get()->buffer()->Unlock(), 0); - - ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle()), 0); - - ASSERT_EQ( - surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/true), - SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess); - } - - // Now that the vr flinger surface is destroyed, vr flinger should deactivate. - ASSERT_EQ( - surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/false), - SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess); -} - -} // namespace dvr -} // namespace android diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.filter b/libs/vr/libvrflinger/tests/vrflinger_test.filter deleted file mode 100644 index 030bb7b67c..0000000000 --- a/libs/vr/libvrflinger/tests/vrflinger_test.filter +++ /dev/null @@ -1,5 +0,0 @@ -{ - "presubmit": { - "filter": "BootVrFlingerTest.*" - } -} diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp deleted file mode 100644 index a8a847664f..0000000000 --- a/libs/vr/libvrflinger/vr_flinger.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include <dvr/vr_flinger.h> - -#include <errno.h> -#include <fcntl.h> -#include <poll.h> -#include <signal.h> -#include <string.h> -#include <time.h> -#include <unistd.h> -#include <memory> - -#include <binder/IServiceManager.h> -#include <binder/ProcessState.h> -#include <cutils/properties.h> -#include <log/log.h> -#include <private/dvr/display_client.h> -#include <processgroup/sched_policy.h> -#include <sys/prctl.h> -#include <sys/resource.h> - -#include <functional> - -#include "DisplayHardware/ComposerHal.h" -#include "display_manager_service.h" -#include "display_service.h" - -namespace android { -namespace dvr { - -std::unique_ptr<VrFlinger> VrFlinger::Create( - Hwc2::Composer* hidl, hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback) { - std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger); - if (vr_flinger->Init(hidl, primary_display_id, request_display_callback)) - return vr_flinger; - else - return nullptr; -} - -VrFlinger::VrFlinger() {} - -VrFlinger::~VrFlinger() { - if (persistent_vr_state_callback_.get()) { - sp<IVrManager> vr_manager = interface_cast<IVrManager>( - defaultServiceManager()->checkService(String16("vrmanager"))); - if (vr_manager.get()) { - vr_manager->unregisterPersistentVrStateListener( - persistent_vr_state_callback_); - } - } - - if (dispatcher_) - dispatcher_->SetCanceled(true); - if (dispatcher_thread_.joinable()) - dispatcher_thread_.join(); -} - -bool VrFlinger::Init(Hwc2::Composer* hidl, - hwc2_display_t primary_display_id, - RequestDisplayCallback request_display_callback) { - if (!hidl || !request_display_callback) - return false; - - std::shared_ptr<android::pdx::Service> service; - - ALOGI("Starting up VrFlinger..."); - - // We need to be able to create endpoints with full perms. - umask(0000); - - android::ProcessState::self()->startThreadPool(); - - request_display_callback_ = request_display_callback; - - dispatcher_ = android::pdx::ServiceDispatcher::Create(); - CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher."); - - display_service_ = android::dvr::DisplayService::Create( - hidl, primary_display_id, request_display_callback); - CHECK_ERROR(!display_service_, error, "Failed to create display service."); - dispatcher_->AddService(display_service_); - - service = android::dvr::DisplayManagerService::Create(display_service_); - CHECK_ERROR(!service, error, "Failed to create display manager service."); - dispatcher_->AddService(service); - - dispatcher_thread_ = std::thread([this]() { - prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0); - ALOGI("Entering message loop."); - - setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY); - set_sched_policy(0, SP_FOREGROUND); - - int ret = dispatcher_->EnterDispatchLoop(); - if (ret < 0) { - ALOGE("Dispatch loop exited because: %s\n", strerror(-ret)); - } - }); - - return true; - -error: - return false; -} - -void VrFlinger::OnBootFinished() { - display_service_->OnBootFinished(); - sp<IVrManager> vr_manager = interface_cast<IVrManager>( - defaultServiceManager()->checkService(String16("vrmanager"))); - if (vr_manager.get()) { - persistent_vr_state_callback_ = - new PersistentVrStateCallback(request_display_callback_); - vr_manager->registerPersistentVrStateListener( - persistent_vr_state_callback_); - } else { - ALOGE("Unable to register vr flinger for persistent vr mode changes"); - } -} - -void VrFlinger::GrantDisplayOwnership() { - display_service_->GrantDisplayOwnership(); -} - -void VrFlinger::SeizeDisplayOwnership() { - display_service_->SeizeDisplayOwnership(); -} - -std::string VrFlinger::Dump() { - // TODO(karthikrs): Add more state information here. - return display_service_->DumpState(0/*unused*/); -} - -void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged( - bool enabled) { - ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off"); - // TODO(eieio): Determine the correct signal to request display control. - // Persistent VR mode is not enough. - // request_display_callback_(enabled); -} -} // namespace dvr -} // namespace android |