1a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include "hardware_composer.h"
2a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <cutils/properties.h>
4a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <cutils/sched_policy.h>
5a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <fcntl.h>
62251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <log/log.h>
7a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <poll.h>
8a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sync/sync.h>
9a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/eventfd.h>
10a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/prctl.h>
11a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/resource.h>
12a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/system_properties.h>
13a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <sys/timerfd.h>
142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <time.h>
15a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <unistd.h>
16a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <utils/Trace.h>
17a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
18a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <algorithm>
192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <chrono>
20a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <functional>
21a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <map>
22a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <dvr/dvr_display_types.h>
24a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <dvr/performance_client_api.h>
25a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <private/dvr/clock_ns.h>
262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#include <private/dvr/ion_buffer.h>
27a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#include <private/dvr/pose_client_internal.h>
28a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
29a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkousing android::pdx::LocalHandle;
302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::rpc::EmptyVariant;
312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::rpc::IfAnyOf;
322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing namespace std::chrono_literals;
34a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
35a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace android {
36a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace dvr {
37a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
38a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkonamespace {
39a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
40a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// If the number of pending fences goes over this count at the point when we
41a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// are about to submit a new frame to HWC, we will drop the frame. This should
42a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// be a signal that the display driver has begun queuing frames. Note that with
43a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// smart displays (with RAM), the fence is signaled earlier than the next vsync,
44a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// at the point when the DMA to the display completes. Currently we use a smart
45a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// display and the EDS timing coincides with zero pending fences, so this is 0.
46a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconstexpr int kAllowedPendingFenceCount = 0;
47a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Offset before vsync to submit frames to hardware composer.
492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakaconstexpr int64_t kFramePostOffsetNs = 4000000;  // 4ms
50a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
51a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconst char kBacklightBrightnessSysFile[] =
52a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    "/sys/class/leds/lcd-backlight/brightness";
53a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
54a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconst char kPrimaryDisplayVSyncEventFile[] =
55a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    "/sys/class/graphics/fb0/vsync_event";
56a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
57a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconst char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
58a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
59a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoconst char kDvrPerformanceProperty[] = "sys.dvr.performance";
60a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
614b78832d7fc3cdd13a20587dfee96d1505916213Luke Songconst char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
62a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
63a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Get time offset from a vsync to when the pose for that vsync should be
64a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// predicted out to. For example, if scanout gets halfway through the frame
65a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// at the halfway point between vsyncs, then this could be half the period.
66a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// With global shutter displays, this should be changed to the offset to when
67a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// illumination begins. Low persistence adds a frame of latency, so we predict
68a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// to the center of the next frame.
69a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoinline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
70a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return (vsync_period_ns * 150) / 100;
71a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
72a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Attempts to set the scheduler class and partiton for the current thread.
742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Returns true on success or false on failure.
752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakabool SetThreadPolicy(const std::string& scheduler_class,
762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                     const std::string& partition) {
772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error < 0) {
792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "thread_id=%d: %s",
822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        scheduler_class.c_str(), gettid(), strerror(-error));
832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return false;
842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = dvrSetCpuPartition(0, partition.c_str());
862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error < 0) {
872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "%s",
902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        partition.c_str(), gettid(), strerror(-error));
912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return false;
922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return true;
942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
96a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}  // anonymous namespace
97a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Layer static data.
992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHwc2::Composer* Layer::hwc2_hidl_;
1002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakaconst HWCDisplayMetrics* Layer::display_metrics_;
1012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// HardwareComposer static data;
1032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakaconstexpr size_t HardwareComposer::kMaxHardwareLayers;
1042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
105a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoHardwareComposer::HardwareComposer()
1062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    : HardwareComposer(nullptr, RequestDisplayCallback()) {}
107a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHardwareComposer::HardwareComposer(
1092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
110016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk    : initialized_(false),
111016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk      hwc2_hidl_(hwc2_hidl),
1122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      request_display_callback_(request_display_callback),
1132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      callbacks_(new ComposerCallback) {}
114a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
115a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoHardwareComposer::~HardwareComposer(void) {
1162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  UpdatePostThreadState(PostThreadState::Quit, true);
1172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (post_thread_.joinable())
118050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    post_thread_.join();
119a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
120a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
121016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazykbool HardwareComposer::Initialize() {
122016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  if (initialized_) {
123016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk    ALOGE("HardwareComposer::Initialize: already initialized.");
124a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return false;
125a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
126a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error = HWC::Error::None;
128a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
129016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  Hwc2::Config config;
1302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
131a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
133016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk    ALOGE("HardwareComposer: Failed to get current display config : %d",
134016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk          config);
135a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return false;
136a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
137a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error =
139016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk      GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
140a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
142016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk    ALOGE(
143016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk        "HardwareComposer: Failed to get display attributes for current "
144016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk        "configuration : %d",
1452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.value);
146a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return false;
147a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
148a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
149a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ALOGI(
150a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      "HardwareComposer: primary display attributes: width=%d height=%d "
151a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      "vsync_period_ns=%d DPI=%dx%d",
152a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      native_display_metrics_.width, native_display_metrics_.height,
153a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      native_display_metrics_.vsync_period_ns, native_display_metrics_.dpi.x,
154a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      native_display_metrics_.dpi.y);
155a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
156016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  // Set the display metrics but never use rotation to avoid the long latency of
157016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  // rotation processing in hwc.
158016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  display_transform_ = HWC_TRANSFORM_NONE;
159016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  display_metrics_ = native_display_metrics_;
160016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk
1612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Pass hwc instance and metrics to setup globals for Layer.
1622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
1632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
165050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  LOG_ALWAYS_FATAL_IF(
1662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      !post_thread_event_fd_,
167050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      "HardwareComposer: Failed to create interrupt event fd : %s",
168050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      strerror(errno));
169050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
170050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  post_thread_ = std::thread(&HardwareComposer::PostThread, this);
171050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
172016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  initialized_ = true;
173016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk
174016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk  return initialized_;
175016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk}
176016e5e3ca751de7e86731349985d1eaf7c072515Stephen Kiazyk
177050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::Enable() {
1782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  UpdatePostThreadState(PostThreadState::Suspended, false);
179050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas}
1807480c060cb3466d97ec3125d61bbace153f534c8Jin Qian
181050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::Disable() {
1822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  UpdatePostThreadState(PostThreadState::Suspended, true);
1832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}
1842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Update the post thread quiescent state based on idle and suspended inputs.
1862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
1872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                             bool suspend) {
188050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  std::unique_lock<std::mutex> lock(post_thread_mutex_);
1892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Update the votes in the state variable before evaluating the effective
1912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // quiescent state. Any bits set in post_thread_state_ indicate that the post
1922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // thread should be suspended.
1932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (suspend) {
1942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_state_ |= state;
1952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  } else {
1962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_state_ &= ~state;
1972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
1982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  const bool quit = post_thread_state_ & PostThreadState::Quit;
2002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
2012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (quit) {
2022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_quiescent_ = true;
2032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    eventfd_write(post_thread_event_fd_.Get(), 1);
2042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_wait_.notify_one();
2052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  } else if (effective_suspend && !post_thread_quiescent_) {
2062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_quiescent_ = true;
2072251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    eventfd_write(post_thread_event_fd_.Get(), 1);
2082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  } else if (!effective_suspend && post_thread_quiescent_) {
2092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_quiescent_ = false;
2102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    eventfd_t value;
2112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    eventfd_read(post_thread_event_fd_.Get(), &value);
2122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    post_thread_wait_.notify_one();
213050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  }
2147480c060cb3466d97ec3125d61bbace153f534c8Jin Qian
2152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Wait until the post thread is in the requested state.
2162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  post_thread_ready_.wait(lock, [this, effective_suspend] {
2172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return effective_suspend != post_thread_resumed_;
2182251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  });
219050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas}
220a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
221050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::OnPostThreadResumed() {
2220af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas  hwc2_hidl_->resetCommands();
2230af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas
224a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Connect to pose service.
225a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  pose_client_ = dvrPoseCreate();
226a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
227a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // HIDL HWC seems to have an internal race condition. If we submit a frame too
2292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // soon after turning on VSync we don't get any VSync signals. Give poor HWC
2302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // implementations a chance to enable VSync before we continue.
2312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  EnableVsync(false);
2322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  std::this_thread::sleep_for(100ms);
233050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  EnableVsync(true);
2342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  std::this_thread::sleep_for(100ms);
235a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
236050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // TODO(skiazyk): We need to do something about accessing this directly,
237050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // supposedly there is a backlight service on the way.
238050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // TODO(steventhomas): When we change the backlight setting, will surface
239050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // flinger (or something else) set it back to its original value once we give
240050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // control of the display back to surface flinger?
241050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  SetBacklightBrightness(255);
242282a5ed48f64e4010f97ca4077e3bd4b54ba3268Steven Thomas
243050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Trigger target-specific performance mode change.
244050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  property_set(kDvrPerformanceProperty, "performance");
245a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
246a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
247050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::OnPostThreadPaused() {
248a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  retire_fence_fds_.clear();
2492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  display_surfaces_.clear();
250a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
251a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
2522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    layers_[i].Reset();
253a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
254a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  active_layer_count_ = 0;
255a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
256050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  if (pose_client_) {
257a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    dvrPoseDestroy(pose_client_);
258050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    pose_client_ = nullptr;
259050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  }
260f43d13e4e35ae7d3cdafc4b97c819669d42cef78Steven Thomas
261050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  EnableVsync(false);
262050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
2630af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas  hwc2_hidl_->resetCommands();
2640af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas
265050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Trigger target-specific performance mode change.
266050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  property_set(kDvrPerformanceProperty, "idle");
267a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
268a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::Validate(hwc2_display_t display) {
270a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  uint32_t num_types;
271a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  uint32_t num_requests;
2722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error =
2732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
274a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
275a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (error == HWC2_ERROR_HAS_CHANGES) {
276a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // TODO(skiazyk): We might need to inspect the requested changes first, but
277a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // so far it seems like we shouldn't ever hit a bad state.
278a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
279a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    //                                               display);
2802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    error = hwc2_hidl_->acceptDisplayChanges(display);
281a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
282a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
283a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return error;
284a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
285a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
286a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint32_t HardwareComposer::EnableVsync(bool enabled) {
287a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return (int32_t)hwc2_hidl_->setVsyncEnabled(
288a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      HWC_DISPLAY_PRIMARY,
289a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
290a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                             : HWC2_VSYNC_DISABLE));
291a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
292a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
2932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::Present(hwc2_display_t display) {
294a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int32_t present_fence;
2952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
296a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
297a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // According to the documentation, this fence is signaled at the time of
298a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // vsync/DMA for physical displays.
2992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error == HWC::Error::None) {
300a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
301a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    retire_fence_fds_.emplace_back(present_fence);
302a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  } else {
303a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ATRACE_INT("HardwareComposer: PresentResult", error);
304a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
305a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
306a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return error;
307a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
308a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
3102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                                 hwc2_config_t config,
3112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                                 hwc2_attribute_t attribute,
3122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                                 int32_t* out_value) const {
3132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return hwc2_hidl_->getDisplayAttribute(
314a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
315a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
316a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaHWC::Error HardwareComposer::GetDisplayMetrics(
318a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    hwc2_display_t display, hwc2_config_t config,
319a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    HWCDisplayMetrics* out_metrics) const {
3202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error;
321a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
3232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              &out_metrics->width);
3242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
3262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::GetDisplayMetrics: Failed to get display width: %s",
3272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.to_string().c_str());
3282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return error;
329a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
330a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
3322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              &out_metrics->height);
3332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
3352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
3362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.to_string().c_str());
3372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return error;
338a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
339a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
3412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              &out_metrics->vsync_period_ns);
3422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
3442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::GetDisplayMetrics: Failed to get display height: %s",
3452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.to_string().c_str());
3462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return error;
347a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
348a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
3502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              &out_metrics->dpi.x);
3512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
3532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI X: %s",
3542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.to_string().c_str());
3552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return error;
356a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
357a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
3592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              &out_metrics->dpi.y);
3602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
3622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::GetDisplayMetrics: Failed to get display DPI Y: %s",
3632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        error.to_string().c_str());
3642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return error;
365a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
366a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return HWC::Error::None;
368a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
369a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakastd::string HardwareComposer::Dump() { return hwc2_hidl_->dumpDebugInfo(); }
371a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid HardwareComposer::PostLayers() {
373a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ATRACE_NAME("HardwareComposer::PostLayers");
374a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
375a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Setup the hardware composer layers with current buffers.
376a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  for (size_t i = 0; i < active_layer_count_; i++) {
3772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    layers_[i].Prepare();
378a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
379a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
3802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
3812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
3822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("HardwareComposer::PostLayers: Validate failed: %s",
3832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          error.to_string().c_str());
3840af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas    return;
3850af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas  }
3860af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas
387a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Now that we have taken in a frame from the application, we have a chance
388a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // to drop the frame before passing the frame along to HWC.
389a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // If the display driver has become backed up, we detect it here and then
390a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // react by skipping this frame to catch up latency.
391a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  while (!retire_fence_fds_.empty() &&
392a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko         (!retire_fence_fds_.front() ||
393a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
394a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // There are only 2 fences in here, no performance problem to shift the
395a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // array of ints.
396a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    retire_fence_fds_.erase(retire_fence_fds_.begin());
397a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
398a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
399a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const bool is_frame_pending = IsFramePendingInDriver();
400a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const bool is_fence_pending =
401a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      retire_fence_fds_.size() > kAllowedPendingFenceCount;
402a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
403a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (is_fence_pending || is_frame_pending) {
404a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ATRACE_INT("frame_skip_count", ++frame_skip_count_);
405a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
406a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
407a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGW_IF(is_fence_pending,
408a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko             "Warning: dropping a frame to catch up with HWC (pending = %zd)",
409a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko             retire_fence_fds_.size());
410a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
411a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    for (size_t i = 0; i < active_layer_count_; i++) {
4122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      layers_[i].Drop();
413a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
414a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return;
415a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  } else {
416a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // Make the transition more obvious in systrace when the frame skip happens
417a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // above.
418a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ATRACE_INT("frame_skip_count", 0);
419a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
420a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
421a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#if TRACE
422a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  for (size_t i = 0; i < active_layer_count_; i++)
4232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGI("HardwareComposer::PostLayers: layer=%zu composition=%s", i,
4242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          layers_[i].GetCompositionType().to_string().c_str());
425a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko#endif
426a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = Present(HWC_DISPLAY_PRIMARY);
4282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (error != HWC::Error::None) {
4292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("HardwareComposer::PostLayers: Present failed: %s",
4302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          error.to_string().c_str());
431a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return;
432a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
433a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
434a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::vector<Hwc2::Layer> out_layers;
435a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::vector<int> out_fences;
4362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
4372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                       &out_fences);
4382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
4392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "HardwareComposer::PostLayers: Failed to get release fences: %s",
4402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
441a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
442a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Perform post-frame bookkeeping. Unused layers are a no-op.
4432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  uint32_t num_elements = out_layers.size();
444a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  for (size_t i = 0; i < num_elements; ++i) {
445a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    for (size_t j = 0; j < active_layer_count_; ++j) {
4462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      if (layers_[j].GetLayerHandle() == out_layers[i]) {
4472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        layers_[j].Finish(out_fences[i]);
448a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      }
449a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
450a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
451a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
452a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
453050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasvoid HardwareComposer::SetDisplaySurfaces(
4542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
455a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
456a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        surfaces.size());
4572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  const bool display_idle = surfaces.size() == 0;
4582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  {
4592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::unique_lock<std::mutex> lock(post_thread_mutex_);
4602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    pending_surfaces_ = std::move(surfaces);
4612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
4622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
4632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Set idle state based on whether there are any surfaces to handle.
4642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  UpdatePostThreadState(PostThreadState::Idle, display_idle);
4652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
4662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // XXX: TEMPORARY
4672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Request control of the display based on whether there are any surfaces to
4682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // handle. This callback sets the post thread active state once the transition
4692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // is complete in SurfaceFlinger.
4702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // TODO(eieio): Unify the control signal used to move SurfaceFlinger into VR
4712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // mode. Currently this is hooked up to persistent VR mode, but perhaps this
4722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // makes more sense to control it from VrCore, which could in turn base its
4732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // decision on persistent VR mode.
4742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (request_display_callback_)
4752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    request_display_callback_(!display_idle);
476050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas}
477a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
4782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakaint HardwareComposer::PostThreadPollInterruptible(
4792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const pdx::LocalHandle& event_fd, int requested_events) {
480050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  pollfd pfd[2] = {
481050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      {
4822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          .fd = event_fd.Get(),
48366747c180e456cc762821c61a75a17bee03a4cf9Steven Thomas          .events = static_cast<short>(requested_events),
48466747c180e456cc762821c61a75a17bee03a4cf9Steven Thomas          .revents = 0,
485050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      },
486050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      {
4872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          .fd = post_thread_event_fd_.Get(),
488050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas          .events = POLLPRI | POLLIN,
489050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas          .revents = 0,
490050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      },
491050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  };
492050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  int ret, error;
493050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  do {
494050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    ret = poll(pfd, 2, -1);
495050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    error = errno;
496050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    ALOGW_IF(ret < 0,
497050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas             "HardwareComposer::PostThreadPollInterruptible: Error during "
498050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas             "poll(): %s (%d)",
499050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas             strerror(error), error);
500050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  } while (ret < 0 && error == EINTR);
5017480c060cb3466d97ec3125d61bbace153f534c8Jin Qian
502050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  if (ret < 0) {
503050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    return -error;
504050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  } else if (pfd[0].revents != 0) {
505050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    return 0;
506050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  } else if (pfd[1].revents != 0) {
507050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    ALOGI("VrHwcPost thread interrupted");
508050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    return kPostThreadInterrupted;
509050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  } else {
510050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    return 0;
5117480c060cb3466d97ec3125d61bbace153f534c8Jin Qian  }
512a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
513a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
514a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
515a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// (the value of the state) on success or a negative error otherwise.
516a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// TODO(eieio): This is pretty driver specific, this should be moved to a
517a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// separate class eventually.
518a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint HardwareComposer::ReadWaitPPState() {
519a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Gracefully handle when the kernel does not support this feature.
520a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (!primary_display_wait_pp_fd_)
521a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return 0;
522a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
523a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
524a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int ret, error;
525a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
526a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ret = lseek(wait_pp_fd, 0, SEEK_SET);
527a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
528a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = errno;
529a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
530a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          strerror(error));
531a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
532a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
533a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
534a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  char data = -1;
535a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ret = read(wait_pp_fd, &data, sizeof(data));
536a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
537a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = errno;
538a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
539a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          strerror(error));
540a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
541a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
542a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
543a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  switch (data) {
544a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    case '0':
545a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      return 0;
546a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    case '1':
547a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      return 1;
548a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    default:
549a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      ALOGE(
550a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
551a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          data);
552a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      return -EINVAL;
553a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
554a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
555a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
556a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Reads the timestamp of the last vsync from the display driver.
557a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// TODO(eieio): This is pretty driver specific, this should be moved to a
558a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// separate class eventually.
559a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
560a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const int event_fd = primary_display_vsync_event_fd_.Get();
561a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int ret, error;
562a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
563a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // The driver returns data in the form "VSYNC=<timestamp ns>".
564a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  std::array<char, 32> data;
565a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  data.fill('\0');
566a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
567a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Seek back to the beginning of the event file.
568a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ret = lseek(event_fd, 0, SEEK_SET);
569a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
570a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = errno;
571a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE(
572a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
573a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "%s",
574a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        strerror(error));
575a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
576a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
577a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
578a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Read the vsync event timestamp.
579a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ret = read(event_fd, data.data(), data.size());
580a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
581a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = errno;
582a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE_IF(
583a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        error != EAGAIN,
584a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
585a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "%s",
586a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        strerror(error));
587a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
588a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
589a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
590a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ret = sscanf(data.data(), "VSYNC=%" PRIu64,
591a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko               reinterpret_cast<uint64_t*>(timestamp));
592a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
593a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = errno;
594a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE(
595a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
596a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        "%s",
597a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        strerror(error));
598a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
599a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
600a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
601a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  return 0;
602a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
603a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
604a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Blocks until the next vsync event is signaled by the display driver.
605a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// TODO(eieio): This is pretty driver specific, this should be moved to a
606a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// separate class eventually.
607050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasint HardwareComposer::BlockUntilVSync() {
6082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Vsync is signaled by POLLPRI on the fb vsync node.
6092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
610a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
611a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
612a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// Waits for the next vsync and returns the timestamp of the vsync event. If
613a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// vsync already passed since the last call, returns the latest vsync timestamp
614a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// instead of blocking. This method updates the last_vsync_timeout_ in the
615a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// process.
616a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko//
617a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// TODO(eieio): This is pretty driver specific, this should be moved to a
618a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko// separate class eventually.
619a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint HardwareComposer::WaitForVSync(int64_t* timestamp) {
620a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int error;
621a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
622a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Get the current timestamp and decide what to do.
623a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  while (true) {
624a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    int64_t current_vsync_timestamp;
625a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    error = ReadVSyncTimestamp(&current_vsync_timestamp);
626a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (error < 0 && error != -EAGAIN)
627a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      return error;
628a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
629a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (error == -EAGAIN) {
630a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Vsync was turned off, wait for the next vsync event.
631050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      error = BlockUntilVSync();
632050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      if (error < 0 || error == kPostThreadInterrupted)
633a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        return error;
634a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
635a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Try again to get the timestamp for this new vsync interval.
636a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      continue;
637a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
638a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
639a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // Check that we advanced to a later vsync interval.
640a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
641a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
642a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      return 0;
643a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
644a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
645a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // See how close we are to the next expected vsync. If we're within 1ms,
646a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // sleep for 1ms and try again.
647a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
6482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const int64_t threshold_ns = 1000000;  // 1ms
649a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
650a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
651a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
652a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
653a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (distance_to_vsync_est > threshold_ns) {
654a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Wait for vsync event notification.
655050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      error = BlockUntilVSync();
656050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      if (error < 0 || error == kPostThreadInterrupted)
657a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        return error;
658a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    } else {
659050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      // Sleep for a short time (1 millisecond) before retrying.
6602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error = SleepUntil(GetSystemClockNs() + threshold_ns);
661050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      if (error < 0 || error == kPostThreadInterrupted)
662050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas        return error;
663a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
664a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
665a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
666a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
667a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkoint HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
668a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const int timer_fd = vsync_sleep_timer_fd_.Get();
669a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const itimerspec wakeup_itimerspec = {
670a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      .it_interval = {.tv_sec = 0, .tv_nsec = 0},
671a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      .it_value = NsToTimespec(wakeup_timestamp),
672a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  };
673a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int ret =
674a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
675a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int error = errno;
676a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (ret < 0) {
677a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
678a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          strerror(error));
679a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return -error;
680a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
681a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
6822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
683a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
684a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
685a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::PostThread() {
686a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // NOLINTNEXTLINE(runtime/int)
687050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
688a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
6892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Set the scheduler to SCHED_FIFO with high priority. If this fails here
6902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // there may have been a startup timing issue between this thread and
6912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // performanced. Try again later when this thread becomes active.
6922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  bool thread_policy_setup =
6932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      SetThreadPolicy("graphics:high", "/system/performance");
694a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
695050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas#if ENABLE_BACKLIGHT_BRIGHTNESS
696050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // TODO(hendrikw): This isn't required at the moment. It's possible that there
697050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  //                 is another method to access this when needed.
698050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Open the backlight brightness control sysfs node.
699050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
700050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  ALOGW_IF(!backlight_brightness_fd_,
701050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas           "HardwareComposer: Failed to open backlight brightness control: %s",
702050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas           strerror(errno));
7032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka#endif  // ENABLE_BACKLIGHT_BRIGHTNESS
704f43d13e4e35ae7d3cdafc4b97c819669d42cef78Steven Thomas
705050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Open the vsync event node for the primary display.
706050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // TODO(eieio): Move this into a platform-specific class.
707050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  primary_display_vsync_event_fd_ =
708050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
709050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  ALOGE_IF(!primary_display_vsync_event_fd_,
710050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas           "HardwareComposer: Failed to open vsync event node for primary "
711050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas           "display: %s",
712050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas           strerror(errno));
713050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
714050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Open the wait pingpong status node for the primary display.
715050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // TODO(eieio): Move this into a platform-specific class.
716050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  primary_display_wait_pp_fd_ =
717050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
718050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  ALOGW_IF(
719050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      !primary_display_wait_pp_fd_,
720050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      "HardwareComposer: Failed to open wait_pp node for primary display: %s",
721050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      strerror(errno));
722050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
723050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  // Create a timerfd based on CLOCK_MONOTINIC.
724050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
725050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  LOG_ALWAYS_FATAL_IF(
726050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      !vsync_sleep_timer_fd_,
727050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      "HardwareComposer: Failed to create vsync sleep timerfd: %s",
728050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      strerror(errno));
729a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
730a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
731a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
732a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
733a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // TODO(jbates) Query vblank time from device, when such an API is available.
734a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // This value (6.3%) was measured on A00 in low persistence mode.
735a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int64_t vblank_ns = ns_per_frame * 63 / 1000;
736a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int64_t right_eye_photon_offset_ns = (ns_per_frame - vblank_ns) / 2;
737a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
738a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Check property for overriding right eye offset value.
739a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  right_eye_photon_offset_ns =
740a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
741a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
742050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  bool was_running = false;
743050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
744a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  while (1) {
745a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ATRACE_NAME("HardwareComposer::PostThread");
746a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
7472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    while (post_thread_quiescent_) {
748050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      std::unique_lock<std::mutex> lock(post_thread_mutex_);
7492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
7502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // Tear down resources.
7522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      OnPostThreadPaused();
7532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      was_running = false;
7552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      post_thread_resumed_ = false;
7562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      post_thread_ready_.notify_all();
7572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      if (post_thread_state_ & PostThreadState::Quit) {
7592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        ALOGI("HardwareComposer::PostThread: Quitting.");
7602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        return;
761282a5ed48f64e4010f97ca4077e3bd4b54ba3268Steven Thomas      }
7622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      post_thread_wait_.wait(lock, [this] { return !post_thread_quiescent_; });
7642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      post_thread_resumed_ = true;
7662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      post_thread_ready_.notify_all();
7672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
769050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    }
770050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
771050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas    if (!was_running) {
7722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // Setup resources.
773050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      OnPostThreadResumed();
774050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      was_running = true;
7752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
7762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // Try to setup the scheduler policy if it failed during startup. Only
7772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // attempt to do this on transitions from inactive to active to avoid
7782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // spamming the system with RPCs and log messages.
7792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      if (!thread_policy_setup) {
7802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        thread_policy_setup =
7812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka            SetThreadPolicy("graphics:high", "/system/performance");
7822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      }
783a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
784a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
785a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    int64_t vsync_timestamp = 0;
786a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    {
787a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      std::array<char, 128> buf;
788a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
789a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko               vsync_count_ + 1);
790a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      ATRACE_NAME(buf.data());
791a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
7922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const int error = WaitForVSync(&vsync_timestamp);
793a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      ALOGE_IF(
794a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          error < 0,
795a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
796a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko          strerror(-error));
797a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Don't bother processing this frame if a pause was requested
798050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      if (error == kPostThreadInterrupted)
799a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        continue;
800a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
801a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
802a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    ++vsync_count_;
803a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
804a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (pose_client_) {
805a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Signal the pose service with vsync info.
806a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      // Display timestamp is in the middle of scanout.
807a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      privateDvrPoseNotifyVsync(pose_client_, vsync_count_,
808a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                vsync_timestamp + photon_offset_ns,
809a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                ns_per_frame, right_eye_photon_offset_ns);
810a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
811a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const bool layer_config_changed = UpdateLayerConfig();
813a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
814a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // Signal all of the vsync clients. Because absolute time is used for the
815a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    // wakeup time below, this can take a little time if necessary.
816a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    if (vsync_callback_)
8172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      vsync_callback_(HWC_DISPLAY_PRIMARY, vsync_timestamp,
8182251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                      /*frame_time_estimate*/ 0, vsync_count_);
819a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
820a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    {
8212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // Sleep until shortly before vsync.
822a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      ATRACE_NAME("sleep");
823a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const int64_t display_time_est_ns = vsync_timestamp + ns_per_frame;
8252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const int64_t now_ns = GetSystemClockNs();
8262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const int64_t sleep_time_ns =
8272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          display_time_est_ns - now_ns - kFramePostOffsetNs;
8282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const int64_t wakeup_time_ns = display_time_est_ns - kFramePostOffsetNs;
829a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
830a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      ATRACE_INT64("sleep_time_ns", sleep_time_ns);
831a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      if (sleep_time_ns > 0) {
8322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        int error = SleepUntil(wakeup_time_ns);
833a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko        ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
834a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                 strerror(-error));
8350af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas        if (error == kPostThreadInterrupted) {
8360af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas          if (layer_config_changed) {
8370af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas            // If the layer config changed we need to validateDisplay() even if
8380af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas            // we're going to drop the frame, to flush the Composer object's
8390af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas            // internal command buffer and apply our layer changes.
8400af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas            Validate(HWC_DISPLAY_PRIMARY);
8410af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas          }
842050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas          continue;
8430af4b9f88a48a6ecc705b4a8cec3d3ba24c53eadSteven Thomas        }
844a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      }
845a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
846a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    PostLayers();
848a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
849a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
850a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// Checks for changes in the surface stack and updates the layer config to
8522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka// accomodate the new stack.
853050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomasbool HardwareComposer::UpdateLayerConfig() {
8542251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
855050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas  {
8562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::unique_lock<std::mutex> lock(post_thread_mutex_);
8572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (pending_surfaces_.empty())
858050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas      return false;
859050b2c83304bd16ec3a838da08b6ba6acf6a3af4Steven Thomas
8602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    surfaces = std::move(pending_surfaces_);
861a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
862a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
863a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ATRACE_NAME("UpdateLayerConfig_HwLayers");
864a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  display_surfaces_.clear();
866a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  Layer* target_layer;
8682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  size_t layer_index;
8692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  for (layer_index = 0;
8702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka       layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
8712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka       layer_index++) {
8722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    // The bottom layer is opaque, other layers blend.
8732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    HWC::BlendMode blending =
8742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
8752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    layers_[layer_index].Setup(surfaces[layer_index], blending,
8762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                               display_transform_, HWC::Composition::Device,
8772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                               layer_index);
8782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    display_surfaces_.push_back(surfaces[layer_index]);
879a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
880a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Clear unused layers.
8822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
8832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    layers_[i].Reset();
884a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  active_layer_count_ = layer_index;
886a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
887a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko           active_layer_count_);
888a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Any surfaces left over could not be assigned a hardware layer and will
8902251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // not be displayed.
8912251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGW_IF(surfaces.size() != display_surfaces_.size(),
8922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
8932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "pending_surfaces=%zu display_surfaces=%zu",
8942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           surfaces.size(), display_surfaces_.size());
895a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
8962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return true;
897a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
898a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
899a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
900a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  vsync_callback_ = callback;
901a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
902a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
903a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
904a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                  hwc2_display_t /*display*/) {
905a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // TODO(eieio): implement invalidate callbacks.
906a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
907a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
908a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
909a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                hwc2_display_t /*display*/,
910a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                int64_t /*timestamp*/) {
911a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  ATRACE_NAME(__PRETTY_FUNCTION__);
912a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // Intentionally empty. HWC may require a callback to be set to enable vsync
913a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // signals. We bypass this callback thread by monitoring the vsync event
914a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // directly, but signals still need to be enabled.
915a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
916a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
917a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
918a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                  hwc2_display_t /*display*/,
919a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko                                  hwc2_connection_t /*connected*/) {
920a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  // TODO(eieio): implement display hotplug callbacks.
921a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
922a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9233cfac28462910d3f976aebac54ac7301aca7e434Steven Thomasvoid HardwareComposer::OnHardwareComposerRefresh() {
9243cfac28462910d3f976aebac54ac7301aca7e434Steven Thomas  // TODO(steventhomas): Handle refresh.
9253cfac28462910d3f976aebac54ac7301aca7e434Steven Thomas}
9263cfac28462910d3f976aebac54ac7301aca7e434Steven Thomas
927a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid HardwareComposer::SetBacklightBrightness(int brightness) {
928a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (backlight_brightness_fd_) {
929a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    std::array<char, 32> text;
930a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    const int length = snprintf(text.data(), text.size(), "%d", brightness);
931a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    write(backlight_brightness_fd_.Get(), text.data(), length);
932a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
933a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
934a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
9362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                              const HWCDisplayMetrics* metrics) {
937a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  hwc2_hidl_ = hwc2_hidl;
938a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  display_metrics_ = metrics;
939a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
940a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
941a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Reset() {
942a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
943a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
944a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    hardware_composer_layer_ = 0;
945a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
946a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  z_order_ = 0;
9482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  blending_ = HWC::BlendMode::None;
9492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  transform_ = HWC::Transform::None;
9502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  composition_type_ = HWC::Composition::Invalid;
9512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  target_composition_type_ = composition_type_;
9522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  source_ = EmptyVariant{};
9532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  acquire_fence_.Close();
954a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  surface_rect_functions_applied_ = false;
955a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
956a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
9582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                  HWC::BlendMode blending, HWC::Transform transform,
9592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                  HWC::Composition composition_type, size_t z_order) {
960a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  Reset();
9612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  z_order_ = z_order;
962a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  blending_ = blending;
963a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  transform_ = transform;
9642251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  composition_type_ = HWC::Composition::Invalid;
9652251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  target_composition_type_ = composition_type;
9662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  source_ = SourceSurface{surface};
967a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  CommonLayerSetup();
968a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
969a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
970a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
9712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                  HWC::BlendMode blending, HWC::Transform transform,
9722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                  HWC::Composition composition_type, size_t z_order) {
973a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  Reset();
9742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  z_order_ = z_order;
975a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  blending_ = blending;
976a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  transform_ = transform;
9772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  composition_type_ = HWC::Composition::Invalid;
9782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  target_composition_type_ = composition_type;
9792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  source_ = SourceBuffer{buffer};
980a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  CommonLayerSetup();
981a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
982a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
9842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (source_.is<SourceBuffer>())
9852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::get<SourceBuffer>(source_) = {buffer};
986a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
987a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
9882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
9892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
990a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
991a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex VakulenkoIonBuffer* Layer::GetBuffer() {
9922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  struct Visitor {
9932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
9942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
9952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    IonBuffer* operator()(EmptyVariant) { return nullptr; }
9962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  };
9972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return source_.Visit(Visitor{});
998a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
999a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1000a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::UpdateLayerSettings() {
1001a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  if (!IsLayerSetup()) {
10022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
10032251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
10042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "unused Layer!");
1005a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    return;
1006a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
1007a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
10082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error;
1009a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  hwc2_display_t display = HWC_DISPLAY_PRIMARY;
1010a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
10112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->setLayerCompositionType(
1012a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      display, hardware_composer_layer_,
10132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      composition_type_.cast<Hwc2::IComposerClient::Composition>());
10142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(
10152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error != HWC::Error::None,
10162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
10172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error.to_string().c_str());
10182251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->setLayerBlendMode(
1020a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko      display, hardware_composer_layer_,
10212251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      blending_.cast<Hwc2::IComposerClient::BlendMode>());
10222251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
10232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
10242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
10252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // TODO(eieio): Use surface attributes or some other mechanism to control
10272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // the layer display frame.
10282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->setLayerDisplayFrame(
10292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      display, hardware_composer_layer_,
10302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      {0, 0, display_metrics_->width, display_metrics_->height});
10312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
10322251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
10332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
10342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error = hwc2_hidl_->setLayerVisibleRegion(
10362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      display, hardware_composer_layer_,
10372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      {{0, 0, display_metrics_->width, display_metrics_->height}});
10382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
10392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
10402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
10412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10422251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error =
10432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
10442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
10452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
10462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
10472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  error =
10492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
10502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(error != HWC::Error::None,
10512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           "Layer::UpdateLayerSettings: Error setting z_ order: %s",
10522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           error.to_string().c_str());
1053a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
1054a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1055a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::CommonLayerSetup() {
10562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  HWC::Error error =
10572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
10582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGE_IF(
10592251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error != HWC::Error::None,
10602251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
10612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error.to_string().c_str());
1062a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  UpdateLayerSettings();
1063a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
1064a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1065a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Prepare() {
1066a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  int right, bottom;
10671f42e3a02c4f9a1ba1916a2f0e47082bedb73e41Daniel Nicoara  sp<GraphicBuffer> handle;
1068a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
10692251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // Acquire the next buffer according to the type of source.
10702251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
10712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
10722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  });
10732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
10742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // When a layer is first setup there may be some time before the first buffer
10752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // arrives. Setup the HWC layer as a solid color to stall for time until the
10762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // first buffer arrives. Once the first buffer arrives there will always be a
10772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  // buffer for the frame even if it is old.
10782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!handle.get()) {
10792251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (composition_type_ == HWC::Composition::Invalid) {
10802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      composition_type_ = HWC::Composition::SolidColor;
10812251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->setLayerCompositionType(
10822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
10832251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          composition_type_.cast<Hwc2::IComposerClient::Composition>());
10842251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
10852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
10862251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                layer_color);
10872251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    } else {
10882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // The composition type is already set. Nothing else to do until a
10892251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      // buffer arrives.
1090a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko    }
1091a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  } else {
10922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (composition_type_ != target_composition_type_) {
10932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      composition_type_ = target_composition_type_;
10942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      hwc2_hidl_->setLayerCompositionType(
10952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
10962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          composition_type_.cast<Hwc2::IComposerClient::Composition>());
10972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
1098a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
10992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    HWC::Error error{HWC::Error::None};
11002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
11012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                       hardware_composer_layer_, 0, handle,
11022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                       acquire_fence_.Get());
1103a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE_IF(error != HWC::Error::None,
11052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka             "Layer::Prepare: Error setting layer buffer: %s",
11062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka             error.to_string().c_str());
1107a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (!surface_rect_functions_applied_) {
11092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const float float_right = right;
11102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      const float float_bottom = bottom;
11112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
11122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                             hardware_composer_layer_,
11132251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka                                             {0, 0, float_right, float_bottom});
1114a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE_IF(error != HWC::Error::None,
11162251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               "Layer::Prepare: Error setting layer source crop: %s",
11172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               error.to_string().c_str());
1118a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      surface_rect_functions_applied_ = true;
11202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
1121a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko  }
1122a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
1123a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1124a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenkovoid Layer::Finish(int release_fence_fd) {
11252251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  IfAnyOf<SourceSurface, SourceBuffer>::Call(
11262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      &source_, [release_fence_fd](auto& source) {
11272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        source.Finish(LocalHandle(release_fence_fd));
11282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      });
1129a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}
1130a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
11312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakavoid Layer::Drop() { acquire_fence_.Close(); }
1132a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko
1133a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}  // namespace dvr
1134a8a92784bc5f6a50ce00311c6161fbcfc0898c5aAlex Vakulenko}  // namespace android
1135