chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_H_
#define UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_H_

#include <stdint.h>
#include <map>
#include <memory>

#include "base/containers/queue.h"
#include "base/files/scoped_file.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "ui/display/types/native_display_delegate.h"
#include "ui/events/ozone/device/device_event.h"
#include "ui/events/ozone/device/device_event_observer.h"
#include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/ozone/platform/drm/common/display_types.h"
#include "ui/ozone/platform/drm/host/gpu_thread_observer.h"
#include "ui/ozone/public/ozone_platform.h"

namespace ui {

class DeviceManager;
class DrmDisplayHost;
class DrmDisplayHostManager;
class DrmNativeDisplayDelegate;
class DrmWrapper;
class GpuThreadAdapter;

// The portion of the DrmDisplayHostManager implementation that is agnostic
// in how its communication with GPU-specific functionality is implemented.
// This is used from both the IPC and the in-process versions in  MUS.
class DrmDisplayHostManager : public DeviceEventObserver, GpuThreadObserver {
 public:
  DrmDisplayHostManager(
      GpuThreadAdapter* proxy,
      DeviceManager* device_manager,
      OzonePlatform::PlatformRuntimeProperties* host_properties,
      InputControllerEvdev* input_controller);

  DrmDisplayHostManager(const DrmDisplayHostManager&) = delete;
  DrmDisplayHostManager& operator=(const DrmDisplayHostManager&) = delete;

  ~DrmDisplayHostManager() override;

  DrmDisplayHost* GetDisplay(int64_t display_id);

  // External API.
  void AddDelegate(DrmNativeDisplayDelegate* delegate);
  void RemoveDelegate(DrmNativeDisplayDelegate* delegate);
  void TakeDisplayControl(display::DisplayControlCallback callback);
  void RelinquishDisplayControl(display::DisplayControlCallback callback);
  void UpdateDisplays(display::GetDisplaysCallback callback);
  void ConfigureDisplays(
      const std::vector<display::DisplayConfigurationParams>& config_requests,
      display::ConfigureCallback callback,
      display::ModesetFlags modeset_flags);

  // DeviceEventObserver overrides:
  void OnDeviceEvent(const DeviceEvent& event) override;

  // GpuThreadObserver overrides:
  void OnGpuProcessLaunched() override;
  void OnGpuThreadReady() override;
  void OnGpuThreadRetired() override;

  // Communication-free implementations of actions performed in response to
  // messages from the GPU thread.
  void GpuHasUpdatedNativeDisplays(MovableDisplaySnapshots displays);
  void GpuSetHdcpKeyProp(int64_t display_id, bool success);
  void GpuReceivedHDCPState(int64_t display_id,
                            bool status,
                            display::HDCPState state,
                            display::ContentProtectionMethod protection_method);
  void GpuUpdatedHDCPState(int64_t display_id, bool status);
  void GpuTookDisplayControl(bool status);
  void GpuRelinquishedDisplayControl(bool status);
  void GpuShouldDisplayEventTriggerConfiguration(bool should_trigger);

 private:
  struct DisplayEvent {
    DisplayEvent(DeviceEvent::ActionType action_type,
                 const base::FilePath& path,
                 const EventPropertyMap& properties);
    DisplayEvent(const DisplayEvent&);
    DisplayEvent& operator=(const DisplayEvent&);
    ~DisplayEvent();

    DeviceEvent::ActionType action_type;
    base::FilePath path;
    EventPropertyMap display_event_props;
  };

  // Handle hotplug events sequentially.
  void ProcessEvent();

  // Called as a result of finishing to process the display hotplug event. These
  // are responsible for dequing the event and scheduling the next event.
  void OnAddGraphicsDevice(const base::FilePath& path,
                           const base::FilePath& sysfs_path,
                           std::unique_ptr<DrmWrapper> drm);
  void OnUpdateGraphicsDevice(const EventPropertyMap& udev_event_props);
  void OnRemoveGraphicsDevice(const base::FilePath& path);

  void RunUpdateDisplaysCallback(display::GetDisplaysCallback callback) const;

  void NotifyDisplayDelegate() const;

  const raw_ptr<GpuThreadAdapter> proxy_;                 // Not owned.
  const raw_ptr<DeviceManager> device_manager_;           // Not owned.
  const raw_ptr<InputControllerEvdev> input_controller_;  // Not owned.

  raw_ptr<DrmNativeDisplayDelegate> delegate_ = nullptr;  // Not owned.

  // File path for the primary graphics card which is opened by default in the
  // GPU process. We'll avoid opening this in hotplug events since it will race
  // with the GPU process trying to open it and aquire DRM master.
  const base::FilePath primary_graphics_card_path_;

  // Keeps track if there is a dummy display. This happens on initialization
  // when there is no connection to the GPU to update the displays.
  bool has_dummy_display_ = false;

  std::vector<std::unique_ptr<DrmDisplayHost>> displays_;

  display::GetDisplaysCallback get_displays_callback_;

  bool display_externally_controlled_ = false;
  bool display_control_change_pending_ = false;
  display::DisplayControlCallback take_display_control_callback_;
  display::DisplayControlCallback relinquish_display_control_callback_;

  // Used to serialize display event processing. This is done since
  // opening/closing DRM devices cannot be done on the UI thread and are handled
  // on a worker thread. Thus, we need to queue events in order to process them
  // in the correct order.
  base::queue<DisplayEvent> event_queue_;

  // True if a display event is currently being processed on a worker thread.
  bool task_pending_ = false;

  // Keeps track of all the active DRM devices. The key is the device path, the
  // value is the sysfs path which has been resolved from the device path.
  std::map<base::FilePath, base::FilePath> drm_devices_;

  // This is used to cache the primary DRM device until the channel is
  // established.
  std::unique_ptr<DrmWrapper> primary_drm_device_;

  // Used to disable input devices when the display is externally controlled.
  std::unique_ptr<ScopedDisableInputDevices> scoped_input_devices_disabler_;

  base::WeakPtrFactory<DrmDisplayHostManager> weak_ptr_factory_{this};
};

}  // namespace ui

#endif  // UI_OZONE_PLATFORM_DRM_HOST_DRM_DISPLAY_HOST_MANAGER_H_