1#include "hardware_composer.h"
2
3#include <cutils/properties.h>
4#include <cutils/sched_policy.h>
5#include <fcntl.h>
6#include <log/log.h>
7#include <poll.h>
8#include <stdint.h>
9#include <sync/sync.h>
10#include <sys/eventfd.h>
11#include <sys/prctl.h>
12#include <sys/resource.h>
13#include <sys/system_properties.h>
14#include <sys/timerfd.h>
15#include <sys/types.h>
16#include <time.h>
17#include <unistd.h>
18#include <utils/Trace.h>
19
20#include <algorithm>
21#include <chrono>
22#include <functional>
23#include <map>
24#include <sstream>
25#include <string>
26#include <tuple>
27
28#include <dvr/dvr_display_types.h>
29#include <dvr/performance_client_api.h>
30#include <private/dvr/clock_ns.h>
31#include <private/dvr/ion_buffer.h>
32
33using android::hardware::Return;
34using android::hardware::Void;
35using android::pdx::ErrorStatus;
36using android::pdx::LocalHandle;
37using android::pdx::Status;
38using android::pdx::rpc::EmptyVariant;
39using android::pdx::rpc::IfAnyOf;
40
41using namespace std::chrono_literals;
42
43namespace android {
44namespace dvr {
45
46namespace {
47
48const char kDvrPerformanceProperty[] = "sys.dvr.performance";
49const char kDvrStandaloneProperty[] = "ro.boot.vr";
50
51const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
52
53const char kUseExternalDisplayProperty[] = "persist.vr.use_external_display";
54
55// How long to wait after boot finishes before we turn the display off.
56constexpr int kBootFinishedDisplayOffTimeoutSec = 10;
57
58constexpr int kDefaultDisplayWidth = 1920;
59constexpr int kDefaultDisplayHeight = 1080;
60constexpr int64_t kDefaultVsyncPeriodNs = 16666667;
61// Hardware composer reports dpi as dots per thousand inches (dpi * 1000).
62constexpr int kDefaultDpi = 400000;
63
64// Get time offset from a vsync to when the pose for that vsync should be
65// predicted out to. For example, if scanout gets halfway through the frame
66// at the halfway point between vsyncs, then this could be half the period.
67// With global shutter displays, this should be changed to the offset to when
68// illumination begins. Low persistence adds a frame of latency, so we predict
69// to the center of the next frame.
70inline int64_t GetPosePredictionTimeOffset(int64_t vsync_period_ns) {
71  return (vsync_period_ns * 150) / 100;
72}
73
74// Attempts to set the scheduler class and partiton for the current thread.
75// Returns true on success or false on failure.
76bool SetThreadPolicy(const std::string& scheduler_class,
77                     const std::string& partition) {
78  int error = dvrSetSchedulerClass(0, scheduler_class.c_str());
79  if (error < 0) {
80    ALOGE(
81        "SetThreadPolicy: Failed to set scheduler class \"%s\" for "
82        "thread_id=%d: %s",
83        scheduler_class.c_str(), gettid(), strerror(-error));
84    return false;
85  }
86  error = dvrSetCpuPartition(0, partition.c_str());
87  if (error < 0) {
88    ALOGE(
89        "SetThreadPolicy: Failed to set cpu partiton \"%s\" for thread_id=%d: "
90        "%s",
91        partition.c_str(), gettid(), strerror(-error));
92    return false;
93  }
94  return true;
95}
96
97// Utility to generate scoped tracers with arguments.
98// TODO(eieio): Move/merge this into utils/Trace.h?
99class TraceArgs {
100 public:
101  template <typename... Args>
102  TraceArgs(const char* format, Args&&... args) {
103    std::array<char, 1024> buffer;
104    snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
105    atrace_begin(ATRACE_TAG, buffer.data());
106  }
107
108  ~TraceArgs() { atrace_end(ATRACE_TAG); }
109
110 private:
111  TraceArgs(const TraceArgs&) = delete;
112  void operator=(const TraceArgs&) = delete;
113};
114
115// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
116// defined in utils/Trace.h.
117#define TRACE_FORMAT(format, ...) \
118  TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
119
120// Returns "primary" or "external". Useful for writing more readable logs.
121const char* GetDisplayName(bool is_primary) {
122  return is_primary ? "primary" : "external";
123}
124
125}  // anonymous namespace
126
127HardwareComposer::HardwareComposer()
128    : initialized_(false), request_display_callback_(nullptr) {}
129
130HardwareComposer::~HardwareComposer(void) {
131  UpdatePostThreadState(PostThreadState::Quit, true);
132  if (post_thread_.joinable())
133    post_thread_.join();
134}
135
136bool HardwareComposer::Initialize(
137    Hwc2::Composer* composer, hwc2_display_t primary_display_id,
138    RequestDisplayCallback request_display_callback) {
139  if (initialized_) {
140    ALOGE("HardwareComposer::Initialize: already initialized.");
141    return false;
142  }
143
144  is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
145
146  request_display_callback_ = request_display_callback;
147
148  primary_display_ = GetDisplayParams(composer, primary_display_id, true);
149
150  post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
151  LOG_ALWAYS_FATAL_IF(
152      !post_thread_event_fd_,
153      "HardwareComposer: Failed to create interrupt event fd : %s",
154      strerror(errno));
155
156  post_thread_ = std::thread(&HardwareComposer::PostThread, this);
157
158  initialized_ = true;
159
160  return initialized_;
161}
162
163void HardwareComposer::Enable() {
164  UpdatePostThreadState(PostThreadState::Suspended, false);
165}
166
167void HardwareComposer::Disable() {
168  UpdatePostThreadState(PostThreadState::Suspended, true);
169
170  std::unique_lock<std::mutex> lock(post_thread_mutex_);
171  post_thread_ready_.wait(lock, [this] {
172    return !post_thread_resumed_;
173  });
174}
175
176void HardwareComposer::OnBootFinished() {
177  std::lock_guard<std::mutex> lock(post_thread_mutex_);
178  if (boot_finished_)
179    return;
180  boot_finished_ = true;
181  post_thread_wait_.notify_one();
182  if (is_standalone_device_)
183    request_display_callback_(true);
184}
185
186// Update the post thread quiescent state based on idle and suspended inputs.
187void HardwareComposer::UpdatePostThreadState(PostThreadStateType state,
188                                             bool suspend) {
189  std::unique_lock<std::mutex> lock(post_thread_mutex_);
190
191  // Update the votes in the state variable before evaluating the effective
192  // quiescent state. Any bits set in post_thread_state_ indicate that the post
193  // thread should be suspended.
194  if (suspend) {
195    post_thread_state_ |= state;
196  } else {
197    post_thread_state_ &= ~state;
198  }
199
200  const bool quit = post_thread_state_ & PostThreadState::Quit;
201  const bool effective_suspend = post_thread_state_ != PostThreadState::Active;
202  if (quit) {
203    post_thread_quiescent_ = true;
204    eventfd_write(post_thread_event_fd_.Get(), 1);
205    post_thread_wait_.notify_one();
206  } else if (effective_suspend && !post_thread_quiescent_) {
207    post_thread_quiescent_ = true;
208    eventfd_write(post_thread_event_fd_.Get(), 1);
209  } else if (!effective_suspend && post_thread_quiescent_) {
210    post_thread_quiescent_ = false;
211    eventfd_t value;
212    eventfd_read(post_thread_event_fd_.Get(), &value);
213    post_thread_wait_.notify_one();
214  }
215}
216
217void HardwareComposer::CreateComposer() {
218  if (composer_)
219    return;
220  composer_.reset(new Hwc2::impl::Composer("default"));
221  composer_callback_ = new ComposerCallback;
222  composer_->registerCallback(composer_callback_);
223  LOG_ALWAYS_FATAL_IF(!composer_callback_->GotFirstHotplug(),
224      "Registered composer callback but didn't get hotplug for primary"
225      " display");
226}
227
228void HardwareComposer::OnPostThreadResumed() {
229  ALOGI("OnPostThreadResumed");
230  EnableDisplay(*target_display_, true);
231
232  // Trigger target-specific performance mode change.
233  property_set(kDvrPerformanceProperty, "performance");
234}
235
236void HardwareComposer::OnPostThreadPaused() {
237  ALOGI("OnPostThreadPaused");
238  retire_fence_fds_.clear();
239  layers_.clear();
240
241  // Phones create a new composer client on resume and destroy it on pause.
242  // Standalones only create the composer client once and then use SetPowerMode
243  // to control the screen on pause/resume.
244  if (!is_standalone_device_) {
245    composer_callback_ = nullptr;
246    composer_.reset(nullptr);
247  } else {
248    EnableDisplay(*target_display_, false);
249  }
250
251  // Trigger target-specific performance mode change.
252  property_set(kDvrPerformanceProperty, "idle");
253}
254
255bool HardwareComposer::PostThreadCondWait(std::unique_lock<std::mutex>& lock,
256                                          int timeout_sec,
257                                          const std::function<bool()>& pred) {
258  auto pred_with_quit = [&] {
259    return pred() || (post_thread_state_ & PostThreadState::Quit);
260  };
261  if (timeout_sec >= 0) {
262    post_thread_wait_.wait_for(lock, std::chrono::seconds(timeout_sec),
263                               pred_with_quit);
264  } else {
265    post_thread_wait_.wait(lock, pred_with_quit);
266  }
267  if (post_thread_state_ & PostThreadState::Quit) {
268    ALOGI("HardwareComposer::PostThread: Quitting.");
269    return true;
270  }
271  return false;
272}
273
274HWC::Error HardwareComposer::Validate(hwc2_display_t display) {
275  uint32_t num_types;
276  uint32_t num_requests;
277  HWC::Error error =
278      composer_->validateDisplay(display, &num_types, &num_requests);
279
280  if (error == HWC2_ERROR_HAS_CHANGES) {
281    ALOGE("Hardware composer has requested composition changes, "
282          "which we don't support.");
283    // Accept the changes anyway and see if we can get something on the screen.
284    error = composer_->acceptDisplayChanges(display);
285  }
286
287  return error;
288}
289
290bool HardwareComposer::EnableVsync(const DisplayParams& display, bool enabled) {
291  HWC::Error error = composer_->setVsyncEnabled(display.id,
292      (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
293                                             : HWC2_VSYNC_DISABLE));
294  if (error != HWC::Error::None) {
295    ALOGE("Error attempting to %s vsync on %s display: %s",
296        enabled ? "enable" : "disable", GetDisplayName(display.is_primary),
297        error.to_string().c_str());
298  }
299  return error == HWC::Error::None;
300}
301
302bool HardwareComposer::SetPowerMode(const DisplayParams& display, bool active) {
303  ALOGI("Turning %s display %s", GetDisplayName(display.is_primary),
304      active ? "on" : "off");
305  HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
306  HWC::Error error = composer_->setPowerMode(display.id,
307      power_mode.cast<Hwc2::IComposerClient::PowerMode>());
308  if (error != HWC::Error::None) {
309    ALOGE("Error attempting to turn %s display %s: %s",
310          GetDisplayName(display.is_primary), active ? "on" : "off",
311        error.to_string().c_str());
312  }
313  return error == HWC::Error::None;
314}
315
316bool HardwareComposer::EnableDisplay(const DisplayParams& display,
317                                     bool enabled) {
318  bool power_result;
319  bool vsync_result;
320  // When turning a display on, we set the power state then set vsync. When
321  // turning a display off we do it in the opposite order.
322  if (enabled) {
323    power_result = SetPowerMode(display, enabled);
324    vsync_result = EnableVsync(display, enabled);
325  } else {
326    vsync_result = EnableVsync(display, enabled);
327    power_result = SetPowerMode(display, enabled);
328  }
329  return power_result && vsync_result;
330}
331
332HWC::Error HardwareComposer::Present(hwc2_display_t display) {
333  int32_t present_fence;
334  HWC::Error error = composer_->presentDisplay(display, &present_fence);
335
336  // According to the documentation, this fence is signaled at the time of
337  // vsync/DMA for physical displays.
338  if (error == HWC::Error::None) {
339    ATRACE_INT("HardwareComposer: VsyncFence", present_fence);
340    retire_fence_fds_.emplace_back(present_fence);
341  } else {
342    ATRACE_INT("HardwareComposer: PresentResult", error);
343  }
344
345  return error;
346}
347
348DisplayParams HardwareComposer::GetDisplayParams(
349    Hwc2::Composer* composer, hwc2_display_t display, bool is_primary) {
350  DisplayParams params;
351  params.id = display;
352  params.is_primary = is_primary;
353
354  Hwc2::Config config;
355  HWC::Error error = composer->getActiveConfig(display, &config);
356
357  if (error == HWC::Error::None) {
358    auto get_attr = [&](hwc2_attribute_t attr, const char* attr_name)
359        -> std::optional<int32_t> {
360      int32_t val;
361      HWC::Error error = composer->getDisplayAttribute(
362          display, config, (Hwc2::IComposerClient::Attribute)attr, &val);
363      if (error != HWC::Error::None) {
364        ALOGE("Failed to get %s display attr %s: %s",
365            GetDisplayName(is_primary), attr_name,
366            error.to_string().c_str());
367        return std::nullopt;
368      }
369      return val;
370    };
371
372    auto width = get_attr(HWC2_ATTRIBUTE_WIDTH, "width");
373    auto height = get_attr(HWC2_ATTRIBUTE_HEIGHT, "height");
374
375    if (width && height) {
376      params.width = *width;
377      params.height = *height;
378    } else {
379      ALOGI("Failed to get width and/or height for %s display. Using default"
380          " size %dx%d.", GetDisplayName(is_primary), kDefaultDisplayWidth,
381          kDefaultDisplayHeight);
382      params.width = kDefaultDisplayWidth;
383      params.height = kDefaultDisplayHeight;
384    }
385
386    auto vsync_period = get_attr(HWC2_ATTRIBUTE_VSYNC_PERIOD, "vsync period");
387    if (vsync_period) {
388      params.vsync_period_ns = *vsync_period;
389    } else {
390      ALOGI("Failed to get vsync period for %s display. Using default vsync"
391          " period %.2fms", GetDisplayName(is_primary),
392          static_cast<float>(kDefaultVsyncPeriodNs) / 1000000);
393      params.vsync_period_ns = kDefaultVsyncPeriodNs;
394    }
395
396    auto dpi_x = get_attr(HWC2_ATTRIBUTE_DPI_X, "DPI X");
397    auto dpi_y = get_attr(HWC2_ATTRIBUTE_DPI_Y, "DPI Y");
398    if (dpi_x && dpi_y) {
399      params.dpi.x = *dpi_x;
400      params.dpi.y = *dpi_y;
401    } else {
402      ALOGI("Failed to get dpi_x and/or dpi_y for %s display. Using default"
403          " dpi %d.", GetDisplayName(is_primary), kDefaultDpi);
404      params.dpi.x = kDefaultDpi;
405      params.dpi.y = kDefaultDpi;
406    }
407  } else {
408    ALOGE("HardwareComposer: Failed to get current %s display config: %d."
409        " Using default display values.",
410        GetDisplayName(is_primary), error.value);
411    params.width = kDefaultDisplayWidth;
412    params.height = kDefaultDisplayHeight;
413    params.dpi.x = kDefaultDpi;
414    params.dpi.y = kDefaultDpi;
415    params.vsync_period_ns = kDefaultVsyncPeriodNs;
416  }
417
418  ALOGI(
419      "HardwareComposer: %s display attributes: width=%d height=%d "
420      "vsync_period_ns=%d DPI=%dx%d",
421      GetDisplayName(is_primary),
422      params.width,
423      params.height,
424      params.vsync_period_ns,
425      params.dpi.x,
426      params.dpi.y);
427
428  return params;
429}
430
431std::string HardwareComposer::Dump() {
432  std::unique_lock<std::mutex> lock(post_thread_mutex_);
433  std::ostringstream stream;
434
435  auto print_display_metrics = [&](const DisplayParams& params) {
436    stream << GetDisplayName(params.is_primary)
437           << " display metrics:     " << params.width << "x"
438           << params.height << " " << (params.dpi.x / 1000.0)
439           << "x" << (params.dpi.y / 1000.0) << " dpi @ "
440           << (1000000000.0 / params.vsync_period_ns) << " Hz"
441           << std::endl;
442  };
443
444  print_display_metrics(primary_display_);
445  if (external_display_)
446    print_display_metrics(*external_display_);
447
448  stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
449  stream << "Active layers:       " << layers_.size() << std::endl;
450  stream << std::endl;
451
452  for (size_t i = 0; i < layers_.size(); i++) {
453    stream << "Layer " << i << ":";
454    stream << " type=" << layers_[i].GetCompositionType().to_string();
455    stream << " surface_id=" << layers_[i].GetSurfaceId();
456    stream << " buffer_id=" << layers_[i].GetBufferId();
457    stream << std::endl;
458  }
459  stream << std::endl;
460
461  if (post_thread_resumed_) {
462    stream << "Hardware Composer Debug Info:" << std::endl;
463    stream << composer_->dumpDebugInfo();
464  }
465
466  return stream.str();
467}
468
469void HardwareComposer::PostLayers(hwc2_display_t display) {
470  ATRACE_NAME("HardwareComposer::PostLayers");
471
472  // Setup the hardware composer layers with current buffers.
473  for (auto& layer : layers_) {
474    layer.Prepare();
475  }
476
477  // Now that we have taken in a frame from the application, we have a chance
478  // to drop the frame before passing the frame along to HWC.
479  // If the display driver has become backed up, we detect it here and then
480  // react by skipping this frame to catch up latency.
481  while (!retire_fence_fds_.empty() &&
482         (!retire_fence_fds_.front() ||
483          sync_wait(retire_fence_fds_.front().Get(), 0) == 0)) {
484    // There are only 2 fences in here, no performance problem to shift the
485    // array of ints.
486    retire_fence_fds_.erase(retire_fence_fds_.begin());
487  }
488
489  const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
490                                post_thread_config_.allowed_pending_fence_count;
491
492  if (is_fence_pending) {
493    ATRACE_INT("frame_skip_count", ++frame_skip_count_);
494
495    ALOGW_IF(is_fence_pending,
496             "Warning: dropping a frame to catch up with HWC (pending = %zd)",
497             retire_fence_fds_.size());
498
499    for (auto& layer : layers_) {
500      layer.Drop();
501    }
502    return;
503  } else {
504    // Make the transition more obvious in systrace when the frame skip happens
505    // above.
506    ATRACE_INT("frame_skip_count", 0);
507  }
508
509#if TRACE > 1
510  for (size_t i = 0; i < layers_.size(); i++) {
511    ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
512          i, layers_[i].GetBufferId(),
513          layers_[i].GetCompositionType().to_string().c_str());
514  }
515#endif
516
517  HWC::Error error = Validate(display);
518  if (error != HWC::Error::None) {
519    ALOGE("HardwareComposer::PostLayers: Validate failed: %s display=%" PRIu64,
520          error.to_string().c_str(), display);
521    return;
522  }
523
524  error = Present(display);
525  if (error != HWC::Error::None) {
526    ALOGE("HardwareComposer::PostLayers: Present failed: %s",
527          error.to_string().c_str());
528    return;
529  }
530
531  std::vector<Hwc2::Layer> out_layers;
532  std::vector<int> out_fences;
533  error = composer_->getReleaseFences(display,
534                                      &out_layers, &out_fences);
535  ALOGE_IF(error != HWC::Error::None,
536           "HardwareComposer::PostLayers: Failed to get release fences: %s",
537           error.to_string().c_str());
538
539  // Perform post-frame bookkeeping.
540  uint32_t num_elements = out_layers.size();
541  for (size_t i = 0; i < num_elements; ++i) {
542    for (auto& layer : layers_) {
543      if (layer.GetLayerHandle() == out_layers[i]) {
544        layer.Finish(out_fences[i]);
545      }
546    }
547  }
548}
549
550void HardwareComposer::SetDisplaySurfaces(
551    std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces) {
552  ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
553        surfaces.size());
554  const bool display_idle = surfaces.size() == 0;
555  {
556    std::unique_lock<std::mutex> lock(post_thread_mutex_);
557    surfaces_ = std::move(surfaces);
558    surfaces_changed_ = true;
559  }
560
561  if (request_display_callback_ && !is_standalone_device_)
562    request_display_callback_(!display_idle);
563
564  // Set idle state based on whether there are any surfaces to handle.
565  UpdatePostThreadState(PostThreadState::Idle, display_idle);
566}
567
568int HardwareComposer::OnNewGlobalBuffer(DvrGlobalBufferKey key,
569                                        IonBuffer& ion_buffer) {
570  if (key == DvrGlobalBuffers::kVsyncBuffer) {
571    vsync_ring_ = std::make_unique<CPUMappedBroadcastRing<DvrVsyncRing>>(
572        &ion_buffer, CPUUsageMode::WRITE_OFTEN);
573
574    if (vsync_ring_->IsMapped() == false) {
575      return -EPERM;
576    }
577  }
578
579  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
580    return MapConfigBuffer(ion_buffer);
581  }
582
583  return 0;
584}
585
586void HardwareComposer::OnDeletedGlobalBuffer(DvrGlobalBufferKey key) {
587  if (key == DvrGlobalBuffers::kVrFlingerConfigBufferKey) {
588    ConfigBufferDeleted();
589  }
590}
591
592int HardwareComposer::MapConfigBuffer(IonBuffer& ion_buffer) {
593  std::lock_guard<std::mutex> lock(shared_config_mutex_);
594  shared_config_ring_ = DvrConfigRing();
595
596  if (ion_buffer.width() < DvrConfigRing::MemorySize()) {
597    ALOGE("HardwareComposer::MapConfigBuffer: invalid buffer size.");
598    return -EINVAL;
599  }
600
601  void* buffer_base = 0;
602  int result = ion_buffer.Lock(ion_buffer.usage(), 0, 0, ion_buffer.width(),
603                               ion_buffer.height(), &buffer_base);
604  if (result != 0) {
605    ALOGE(
606        "HardwareComposer::MapConfigBuffer: Failed to map vrflinger config "
607        "buffer.");
608    return -EPERM;
609  }
610
611  shared_config_ring_ = DvrConfigRing::Create(buffer_base, ion_buffer.width());
612  ion_buffer.Unlock();
613
614  return 0;
615}
616
617void HardwareComposer::ConfigBufferDeleted() {
618  std::lock_guard<std::mutex> lock(shared_config_mutex_);
619  shared_config_ring_ = DvrConfigRing();
620}
621
622void HardwareComposer::UpdateConfigBuffer() {
623  std::lock_guard<std::mutex> lock(shared_config_mutex_);
624  if (!shared_config_ring_.is_valid())
625    return;
626  // Copy from latest record in shared_config_ring_ to local copy.
627  DvrConfig record;
628  if (shared_config_ring_.GetNewest(&shared_config_ring_sequence_, &record)) {
629    ALOGI("DvrConfig updated: sequence %u, post offset %d",
630          shared_config_ring_sequence_, record.frame_post_offset_ns);
631    ++shared_config_ring_sequence_;
632    post_thread_config_ = record;
633  }
634}
635
636int HardwareComposer::PostThreadPollInterruptible(
637    const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
638  pollfd pfd[2] = {
639      {
640          .fd = event_fd.Get(),
641          .events = static_cast<short>(requested_events),
642          .revents = 0,
643      },
644      {
645          .fd = post_thread_event_fd_.Get(),
646          .events = POLLPRI | POLLIN,
647          .revents = 0,
648      },
649  };
650  int ret, error;
651  do {
652    ret = poll(pfd, 2, timeout_ms);
653    error = errno;
654    ALOGW_IF(ret < 0,
655             "HardwareComposer::PostThreadPollInterruptible: Error during "
656             "poll(): %s (%d)",
657             strerror(error), error);
658  } while (ret < 0 && error == EINTR);
659
660  if (ret < 0) {
661    return -error;
662  } else if (ret == 0) {
663    return -ETIMEDOUT;
664  } else if (pfd[0].revents != 0) {
665    return 0;
666  } else if (pfd[1].revents != 0) {
667    ALOGI("VrHwcPost thread interrupted: revents=%x", pfd[1].revents);
668    return kPostThreadInterrupted;
669  } else {
670    return 0;
671  }
672}
673
674// Sleep until the next predicted vsync, returning the predicted vsync
675// timestamp.
676Status<int64_t> HardwareComposer::WaitForPredictedVSync() {
677  const int64_t predicted_vsync_time = last_vsync_timestamp_ +
678      (target_display_->vsync_period_ns * vsync_prediction_interval_);
679  const int error = SleepUntil(predicted_vsync_time);
680  if (error < 0) {
681    ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
682          strerror(-error));
683    return error;
684  }
685  return {predicted_vsync_time};
686}
687
688int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
689  const int timer_fd = vsync_sleep_timer_fd_.Get();
690  const itimerspec wakeup_itimerspec = {
691      .it_interval = {.tv_sec = 0, .tv_nsec = 0},
692      .it_value = NsToTimespec(wakeup_timestamp),
693  };
694  int ret =
695      timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &wakeup_itimerspec, nullptr);
696  int error = errno;
697  if (ret < 0) {
698    ALOGE("HardwareComposer::SleepUntil: Failed to set timerfd: %s",
699          strerror(error));
700    return -error;
701  }
702
703  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
704                                     /*timeout_ms*/ -1);
705}
706
707void HardwareComposer::PostThread() {
708  // NOLINTNEXTLINE(runtime/int)
709  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
710
711  // Set the scheduler to SCHED_FIFO with high priority. If this fails here
712  // there may have been a startup timing issue between this thread and
713  // performanced. Try again later when this thread becomes active.
714  bool thread_policy_setup =
715      SetThreadPolicy("graphics:high", "/system/performance");
716
717  // Create a timerfd based on CLOCK_MONOTINIC.
718  vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
719  LOG_ALWAYS_FATAL_IF(
720      !vsync_sleep_timer_fd_,
721      "HardwareComposer: Failed to create vsync sleep timerfd: %s",
722      strerror(errno));
723
724  struct VsyncEyeOffsets { int64_t left_ns, right_ns; };
725  bool was_running = false;
726
727  auto get_vsync_eye_offsets = [this]() -> VsyncEyeOffsets {
728    VsyncEyeOffsets offsets;
729    offsets.left_ns =
730        GetPosePredictionTimeOffset(target_display_->vsync_period_ns);
731
732    // TODO(jbates) Query vblank time from device, when such an API is
733    // available. This value (6.3%) was measured on A00 in low persistence mode.
734    int64_t vblank_ns = target_display_->vsync_period_ns * 63 / 1000;
735    offsets.right_ns = (target_display_->vsync_period_ns - vblank_ns) / 2;
736
737    // Check property for overriding right eye offset value.
738    offsets.right_ns =
739        property_get_int64(kRightEyeOffsetProperty, offsets.right_ns);
740
741    return offsets;
742  };
743
744  VsyncEyeOffsets vsync_eye_offsets = get_vsync_eye_offsets();
745
746  if (is_standalone_device_) {
747    // First, wait until boot finishes.
748    std::unique_lock<std::mutex> lock(post_thread_mutex_);
749    if (PostThreadCondWait(lock, -1, [this] { return boot_finished_; })) {
750      return;
751    }
752
753    // Then, wait until we're either leaving the quiescent state, or the boot
754    // finished display off timeout expires.
755    if (PostThreadCondWait(lock, kBootFinishedDisplayOffTimeoutSec,
756                           [this] { return !post_thread_quiescent_; })) {
757      return;
758    }
759
760    LOG_ALWAYS_FATAL_IF(post_thread_state_ & PostThreadState::Suspended,
761                        "Vr flinger should own the display by now.");
762    post_thread_resumed_ = true;
763    post_thread_ready_.notify_all();
764    if (!composer_)
765      CreateComposer();
766  }
767
768  while (1) {
769    ATRACE_NAME("HardwareComposer::PostThread");
770
771    // Check for updated config once per vsync.
772    UpdateConfigBuffer();
773
774    while (post_thread_quiescent_) {
775      std::unique_lock<std::mutex> lock(post_thread_mutex_);
776      ALOGI("HardwareComposer::PostThread: Entering quiescent state.");
777
778      // Tear down resources.
779      OnPostThreadPaused();
780      was_running = false;
781      post_thread_resumed_ = false;
782      post_thread_ready_.notify_all();
783
784      if (PostThreadCondWait(lock, -1,
785                             [this] { return !post_thread_quiescent_; })) {
786        // A true return value means we've been asked to quit.
787        return;
788      }
789
790      post_thread_resumed_ = true;
791      post_thread_ready_.notify_all();
792
793      ALOGI("HardwareComposer::PostThread: Exiting quiescent state.");
794    }
795
796    if (!composer_)
797      CreateComposer();
798
799    bool target_display_changed = UpdateTargetDisplay();
800    bool just_resumed_running = !was_running;
801    was_running = true;
802
803    if (target_display_changed)
804      vsync_eye_offsets = get_vsync_eye_offsets();
805
806    if (just_resumed_running) {
807      OnPostThreadResumed();
808
809      // Try to setup the scheduler policy if it failed during startup. Only
810      // attempt to do this on transitions from inactive to active to avoid
811      // spamming the system with RPCs and log messages.
812      if (!thread_policy_setup) {
813        thread_policy_setup =
814            SetThreadPolicy("graphics:high", "/system/performance");
815      }
816    }
817
818    if (target_display_changed || just_resumed_running) {
819      // Initialize the last vsync timestamp with the current time. The
820      // predictor below uses this time + the vsync interval in absolute time
821      // units for the initial delay. Once the driver starts reporting vsync the
822      // predictor will sync up with the real vsync.
823      last_vsync_timestamp_ = GetSystemClockNs();
824      vsync_prediction_interval_ = 1;
825      retire_fence_fds_.clear();
826    }
827
828    int64_t vsync_timestamp = 0;
829    {
830      TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64
831                   ";prediction_interval=%d|",
832                   vsync_count_ + 1, last_vsync_timestamp_,
833                   vsync_prediction_interval_);
834
835      auto status = WaitForPredictedVSync();
836      ALOGE_IF(
837          !status,
838          "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
839          status.GetErrorMessage().c_str());
840
841      // If there was an error either sleeping was interrupted due to pausing or
842      // there was an error getting the latest timestamp.
843      if (!status)
844        continue;
845
846      // Predicted vsync timestamp for this interval. This is stable because we
847      // use absolute time for the wakeup timer.
848      vsync_timestamp = status.get();
849    }
850
851    // Advance the vsync counter only if the system is keeping up with hardware
852    // vsync to give clients an indication of the delays.
853    if (vsync_prediction_interval_ == 1)
854      ++vsync_count_;
855
856    UpdateLayerConfig();
857
858    // Publish the vsync event.
859    if (vsync_ring_) {
860      DvrVsync vsync;
861      vsync.vsync_count = vsync_count_;
862      vsync.vsync_timestamp_ns = vsync_timestamp;
863      vsync.vsync_left_eye_offset_ns = vsync_eye_offsets.left_ns;
864      vsync.vsync_right_eye_offset_ns = vsync_eye_offsets.right_ns;
865      vsync.vsync_period_ns = target_display_->vsync_period_ns;
866
867      vsync_ring_->Publish(vsync);
868    }
869
870    // Signal all of the vsync clients. Because absolute time is used for the
871    // wakeup time below, this can take a little time if necessary.
872    if (vsync_callback_)
873      vsync_callback_(vsync_timestamp, /*frame_time_estimate*/ 0, vsync_count_);
874
875    {
876      // Sleep until shortly before vsync.
877      ATRACE_NAME("sleep");
878
879      const int64_t display_time_est_ns =
880          vsync_timestamp + target_display_->vsync_period_ns;
881      const int64_t now_ns = GetSystemClockNs();
882      const int64_t sleep_time_ns = display_time_est_ns - now_ns -
883                                    post_thread_config_.frame_post_offset_ns;
884      const int64_t wakeup_time_ns =
885          display_time_est_ns - post_thread_config_.frame_post_offset_ns;
886
887      ATRACE_INT64("sleep_time_ns", sleep_time_ns);
888      if (sleep_time_ns > 0) {
889        int error = SleepUntil(wakeup_time_ns);
890        ALOGE_IF(error < 0 && error != kPostThreadInterrupted,
891                 "HardwareComposer::PostThread: Failed to sleep: %s",
892                 strerror(-error));
893        // If the sleep was interrupted (error == kPostThreadInterrupted),
894        // we still go through and present this frame because we may have set
895        // layers earlier and we want to flush the Composer's internal command
896        // buffer by continuing through to validate and present.
897      }
898    }
899
900    {
901      auto status = composer_callback_->GetVsyncTime(target_display_->id);
902
903      // If we failed to read vsync there might be a problem with the driver.
904      // Since there's nothing we can do just behave as though we didn't get an
905      // updated vsync time and let the prediction continue.
906      const int64_t current_vsync_timestamp =
907          status ? status.get() : last_vsync_timestamp_;
908
909      const bool vsync_delayed =
910          last_vsync_timestamp_ == current_vsync_timestamp;
911      ATRACE_INT("vsync_delayed", vsync_delayed);
912
913      // If vsync was delayed advance the prediction interval and allow the
914      // fence logic in PostLayers() to skip the frame.
915      if (vsync_delayed) {
916        ALOGW(
917            "HardwareComposer::PostThread: VSYNC timestamp did not advance "
918            "since last frame: timestamp=%" PRId64 " prediction_interval=%d",
919            current_vsync_timestamp, vsync_prediction_interval_);
920        vsync_prediction_interval_++;
921      } else {
922        // We have an updated vsync timestamp, reset the prediction interval.
923        last_vsync_timestamp_ = current_vsync_timestamp;
924        vsync_prediction_interval_ = 1;
925      }
926    }
927
928    PostLayers(target_display_->id);
929  }
930}
931
932bool HardwareComposer::UpdateTargetDisplay() {
933  bool target_display_changed = false;
934  auto displays = composer_callback_->GetDisplays();
935  if (displays.external_display_was_hotplugged) {
936    bool was_using_external_display = !target_display_->is_primary;
937    if (was_using_external_display) {
938      // The external display was hotplugged, so make sure to ignore any bad
939      // display errors as we destroy the layers.
940      for (auto& layer: layers_)
941        layer.IgnoreBadDisplayErrorsOnDestroy(true);
942    }
943
944    if (displays.external_display) {
945      // External display was connected
946      external_display_ = GetDisplayParams(composer_.get(),
947          *displays.external_display, /*is_primary*/ false);
948
949      if (property_get_bool(kUseExternalDisplayProperty, false)) {
950        ALOGI("External display connected. Switching to external display.");
951        target_display_ = &(*external_display_);
952        target_display_changed = true;
953      } else {
954        ALOGI("External display connected, but sysprop %s is unset, so"
955              " using primary display.", kUseExternalDisplayProperty);
956        if (was_using_external_display) {
957          target_display_ = &primary_display_;
958          target_display_changed = true;
959        }
960      }
961    } else {
962      // External display was disconnected
963      external_display_ = std::nullopt;
964      if (was_using_external_display) {
965        ALOGI("External display disconnected. Switching to primary display.");
966        target_display_ = &primary_display_;
967        target_display_changed = true;
968      }
969    }
970  }
971
972  if (target_display_changed) {
973    // If we're switching to the external display, turn the primary display off.
974    if (!target_display_->is_primary) {
975      EnableDisplay(primary_display_, false);
976    }
977    // If we're switching to the primary display, and the external display is
978    // still connected, turn the external display off.
979    else if (target_display_->is_primary && external_display_) {
980      EnableDisplay(*external_display_, false);
981    }
982
983    // Turn the new target display on.
984    EnableDisplay(*target_display_, true);
985
986    // When we switch displays we need to recreate all the layers, so clear the
987    // current list, which will trigger layer recreation.
988    layers_.clear();
989  }
990
991  return target_display_changed;
992}
993
994// Checks for changes in the surface stack and updates the layer config to
995// accomodate the new stack.
996void HardwareComposer::UpdateLayerConfig() {
997  std::vector<std::shared_ptr<DirectDisplaySurface>> surfaces;
998  {
999    std::unique_lock<std::mutex> lock(post_thread_mutex_);
1000
1001    if (!surfaces_changed_ && (!layers_.empty() || surfaces_.empty()))
1002      return;
1003
1004    surfaces = surfaces_;
1005    surfaces_changed_ = false;
1006  }
1007
1008  ATRACE_NAME("UpdateLayerConfig_HwLayers");
1009
1010  // Sort the new direct surface list by z-order to determine the relative order
1011  // of the surfaces. This relative order is used for the HWC z-order value to
1012  // insulate VrFlinger and HWC z-order semantics from each other.
1013  std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
1014    return a->z_order() < b->z_order();
1015  });
1016
1017  // Prepare a new layer stack, pulling in layers from the previous
1018  // layer stack that are still active and updating their attributes.
1019  std::vector<Layer> layers;
1020  size_t layer_index = 0;
1021  for (const auto& surface : surfaces) {
1022    // The bottom layer is opaque, other layers blend.
1023    HWC::BlendMode blending =
1024        layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
1025
1026    // Try to find a layer for this surface in the set of active layers.
1027    auto search =
1028        std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
1029    const bool found = search != layers_.end() &&
1030                       search->GetSurfaceId() == surface->surface_id();
1031    if (found) {
1032      // Update the attributes of the layer that may have changed.
1033      search->SetBlending(blending);
1034      search->SetZOrder(layer_index);  // Relative z-order.
1035
1036      // Move the existing layer to the new layer set and remove the empty layer
1037      // object from the current set.
1038      layers.push_back(std::move(*search));
1039      layers_.erase(search);
1040    } else {
1041      // Insert a layer for the new surface.
1042      layers.emplace_back(composer_.get(), *target_display_, surface, blending,
1043          HWC::Composition::Device, layer_index);
1044    }
1045
1046    ALOGI_IF(
1047        TRACE,
1048        "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
1049        layer_index, layers[layer_index].GetSurfaceId());
1050
1051    layer_index++;
1052  }
1053
1054  // Sort the new layer stack by ascending surface id.
1055  std::sort(layers.begin(), layers.end());
1056
1057  // Replace the previous layer set with the new layer set. The destructor of
1058  // the previous set will clean up the remaining Layers that are not moved to
1059  // the new layer set.
1060  layers_ = std::move(layers);
1061
1062  ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
1063           layers_.size());
1064}
1065
1066void HardwareComposer::SetVSyncCallback(VSyncCallback callback) {
1067  vsync_callback_ = callback;
1068}
1069
1070Return<void> HardwareComposer::ComposerCallback::onHotplug(
1071    Hwc2::Display display, IComposerCallback::Connection conn) {
1072  std::lock_guard<std::mutex> lock(mutex_);
1073  ALOGI("onHotplug display=%" PRIu64 " conn=%d", display, conn);
1074
1075  bool is_primary = !got_first_hotplug_ || display == primary_display_.id;
1076
1077  // Our first onHotplug callback is always for the primary display.
1078  if (!got_first_hotplug_) {
1079    LOG_ALWAYS_FATAL_IF(conn != IComposerCallback::Connection::CONNECTED,
1080        "Initial onHotplug callback should be primary display connected");
1081    got_first_hotplug_ = true;
1082  } else if (is_primary) {
1083    ALOGE("Ignoring unexpected onHotplug() call for primary display");
1084    return Void();
1085  }
1086
1087  if (conn == IComposerCallback::Connection::CONNECTED) {
1088    if (!is_primary)
1089      external_display_ = DisplayInfo();
1090    DisplayInfo& display_info = is_primary ?
1091        primary_display_ : *external_display_;
1092    display_info.id = display;
1093
1094    std::array<char, 1024> buffer;
1095    snprintf(buffer.data(), buffer.size(),
1096             "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
1097    if (LocalHandle handle{buffer.data(), O_RDONLY}) {
1098      ALOGI(
1099          "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
1100          "vsync_event node for display %" PRIu64,
1101          display);
1102      display_info.driver_vsync_event_fd = std::move(handle);
1103    } else {
1104      ALOGI(
1105          "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
1106          "support vsync_event node for display %" PRIu64,
1107          display);
1108    }
1109  } else if (conn == IComposerCallback::Connection::DISCONNECTED) {
1110    external_display_ = std::nullopt;
1111  }
1112
1113  if (!is_primary)
1114    external_display_was_hotplugged_ = true;
1115
1116  return Void();
1117}
1118
1119Return<void> HardwareComposer::ComposerCallback::onRefresh(
1120    Hwc2::Display /*display*/) {
1121  return hardware::Void();
1122}
1123
1124Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
1125                                                         int64_t timestamp) {
1126  DisplayInfo* display_info = GetDisplayInfo(display);
1127  if (display_info) {
1128    TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
1129                 display, timestamp);
1130    display_info->callback_vsync_timestamp = timestamp;
1131  }
1132
1133  return Void();
1134}
1135
1136HardwareComposer::ComposerCallback::Displays
1137HardwareComposer::ComposerCallback::GetDisplays() {
1138  std::lock_guard<std::mutex> lock(mutex_);
1139  Displays displays;
1140  displays.primary_display = primary_display_.id;
1141  if (external_display_)
1142    displays.external_display = external_display_->id;
1143  if (external_display_was_hotplugged_) {
1144    external_display_was_hotplugged_ = false;
1145    displays.external_display_was_hotplugged = true;
1146  }
1147  return displays;
1148}
1149
1150Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
1151    hwc2_display_t display) {
1152  DisplayInfo* display_info = GetDisplayInfo(display);
1153  if (!display_info) {
1154    ALOGW("Attempt to get vsync time for unknown display %" PRIu64, display);
1155    return ErrorStatus(EINVAL);
1156  }
1157
1158  // See if the driver supports direct vsync events.
1159  LocalHandle& event_fd = display_info->driver_vsync_event_fd;
1160  if (!event_fd) {
1161    // Fall back to returning the last timestamp returned by the vsync
1162    // callback.
1163    std::lock_guard<std::mutex> autolock(mutex_);
1164    return display_info->callback_vsync_timestamp;
1165  }
1166
1167  // When the driver supports the vsync_event sysfs node we can use it to
1168  // determine the latest vsync timestamp, even if the HWC callback has been
1169  // delayed.
1170
1171  // The driver returns data in the form "VSYNC=<timestamp ns>".
1172  std::array<char, 32> data;
1173  data.fill('\0');
1174
1175  // Seek back to the beginning of the event file.
1176  int ret = lseek(event_fd.Get(), 0, SEEK_SET);
1177  if (ret < 0) {
1178    const int error = errno;
1179    ALOGE(
1180        "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek "
1181        "vsync event fd: %s",
1182        strerror(error));
1183    return ErrorStatus(error);
1184  }
1185
1186  // Read the vsync event timestamp.
1187  ret = read(event_fd.Get(), data.data(), data.size());
1188  if (ret < 0) {
1189    const int error = errno;
1190    ALOGE_IF(error != EAGAIN,
1191             "HardwareComposer::ComposerCallback::GetVsyncTime: Error "
1192             "while reading timestamp: %s",
1193             strerror(error));
1194    return ErrorStatus(error);
1195  }
1196
1197  int64_t timestamp;
1198  ret = sscanf(data.data(), "VSYNC=%" PRIu64,
1199               reinterpret_cast<uint64_t*>(&timestamp));
1200  if (ret < 0) {
1201    const int error = errno;
1202    ALOGE(
1203        "HardwareComposer::ComposerCallback::GetVsyncTime: Error while "
1204        "parsing timestamp: %s",
1205        strerror(error));
1206    return ErrorStatus(error);
1207  }
1208
1209  return {timestamp};
1210}
1211
1212HardwareComposer::ComposerCallback::DisplayInfo*
1213HardwareComposer::ComposerCallback::GetDisplayInfo(hwc2_display_t display) {
1214  if (display == primary_display_.id) {
1215    return &primary_display_;
1216  } else if (external_display_ && display == external_display_->id) {
1217    return &(*external_display_);
1218  }
1219  return nullptr;
1220}
1221
1222void Layer::Reset() {
1223  if (hardware_composer_layer_) {
1224    HWC::Error error =
1225        composer_->destroyLayer(display_params_.id, hardware_composer_layer_);
1226    if (error != HWC::Error::None &&
1227        (!ignore_bad_display_errors_on_destroy_ ||
1228         error != HWC::Error::BadDisplay)) {
1229      ALOGE("destroyLayer() failed for display %" PRIu64 ", layer %" PRIu64
1230          ". error: %s", display_params_.id, hardware_composer_layer_,
1231          error.to_string().c_str());
1232    }
1233    hardware_composer_layer_ = 0;
1234  }
1235
1236  z_order_ = 0;
1237  blending_ = HWC::BlendMode::None;
1238  composition_type_ = HWC::Composition::Invalid;
1239  target_composition_type_ = composition_type_;
1240  source_ = EmptyVariant{};
1241  acquire_fence_.Close();
1242  surface_rect_functions_applied_ = false;
1243  pending_visibility_settings_ = true;
1244  cached_buffer_map_.clear();
1245  ignore_bad_display_errors_on_destroy_ = false;
1246}
1247
1248Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1249             const std::shared_ptr<DirectDisplaySurface>& surface,
1250             HWC::BlendMode blending, HWC::Composition composition_type,
1251             size_t z_order)
1252    : composer_(composer),
1253      display_params_(display_params),
1254      z_order_{z_order},
1255      blending_{blending},
1256      target_composition_type_{composition_type},
1257      source_{SourceSurface{surface}} {
1258  CommonLayerSetup();
1259}
1260
1261Layer::Layer(Hwc2::Composer* composer, const DisplayParams& display_params,
1262             const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
1263             HWC::Composition composition_type, size_t z_order)
1264    : composer_(composer),
1265      display_params_(display_params),
1266      z_order_{z_order},
1267      blending_{blending},
1268      target_composition_type_{composition_type},
1269      source_{SourceBuffer{buffer}} {
1270  CommonLayerSetup();
1271}
1272
1273Layer::~Layer() { Reset(); }
1274
1275Layer::Layer(Layer&& other) { *this = std::move(other); }
1276
1277Layer& Layer::operator=(Layer&& other) {
1278  if (this != &other) {
1279    Reset();
1280    using std::swap;
1281    swap(composer_, other.composer_);
1282    swap(display_params_, other.display_params_);
1283    swap(hardware_composer_layer_, other.hardware_composer_layer_);
1284    swap(z_order_, other.z_order_);
1285    swap(blending_, other.blending_);
1286    swap(composition_type_, other.composition_type_);
1287    swap(target_composition_type_, other.target_composition_type_);
1288    swap(source_, other.source_);
1289    swap(acquire_fence_, other.acquire_fence_);
1290    swap(surface_rect_functions_applied_,
1291         other.surface_rect_functions_applied_);
1292    swap(pending_visibility_settings_, other.pending_visibility_settings_);
1293    swap(cached_buffer_map_, other.cached_buffer_map_);
1294    swap(ignore_bad_display_errors_on_destroy_,
1295         other.ignore_bad_display_errors_on_destroy_);
1296  }
1297  return *this;
1298}
1299
1300void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
1301  if (source_.is<SourceBuffer>())
1302    std::get<SourceBuffer>(source_) = {buffer};
1303}
1304
1305void Layer::SetBlending(HWC::BlendMode blending) {
1306  if (blending_ != blending) {
1307    blending_ = blending;
1308    pending_visibility_settings_ = true;
1309  }
1310}
1311
1312void Layer::SetZOrder(size_t z_order) {
1313  if (z_order_ != z_order) {
1314    z_order_ = z_order;
1315    pending_visibility_settings_ = true;
1316  }
1317}
1318
1319IonBuffer* Layer::GetBuffer() {
1320  struct Visitor {
1321    IonBuffer* operator()(SourceSurface& source) { return source.GetBuffer(); }
1322    IonBuffer* operator()(SourceBuffer& source) { return source.GetBuffer(); }
1323    IonBuffer* operator()(EmptyVariant) { return nullptr; }
1324  };
1325  return source_.Visit(Visitor{});
1326}
1327
1328void Layer::UpdateVisibilitySettings() {
1329  if (pending_visibility_settings_) {
1330    pending_visibility_settings_ = false;
1331
1332    HWC::Error error;
1333
1334    error = composer_->setLayerBlendMode(
1335        display_params_.id, hardware_composer_layer_,
1336        blending_.cast<Hwc2::IComposerClient::BlendMode>());
1337    ALOGE_IF(error != HWC::Error::None,
1338             "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
1339             error.to_string().c_str());
1340
1341    error = composer_->setLayerZOrder(display_params_.id,
1342        hardware_composer_layer_, z_order_);
1343    ALOGE_IF(error != HWC::Error::None,
1344             "Layer::UpdateLayerSettings: Error setting z_ order: %s",
1345             error.to_string().c_str());
1346  }
1347}
1348
1349void Layer::UpdateLayerSettings() {
1350  HWC::Error error;
1351
1352  UpdateVisibilitySettings();
1353
1354  // TODO(eieio): Use surface attributes or some other mechanism to control
1355  // the layer display frame.
1356  error = composer_->setLayerDisplayFrame(
1357      display_params_.id, hardware_composer_layer_,
1358      {0, 0, display_params_.width, display_params_.height});
1359  ALOGE_IF(error != HWC::Error::None,
1360           "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
1361           error.to_string().c_str());
1362
1363  error = composer_->setLayerVisibleRegion(
1364      display_params_.id, hardware_composer_layer_,
1365      {{0, 0, display_params_.width, display_params_.height}});
1366  ALOGE_IF(error != HWC::Error::None,
1367           "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
1368           error.to_string().c_str());
1369
1370  error = composer_->setLayerPlaneAlpha(display_params_.id,
1371      hardware_composer_layer_, 1.0f);
1372  ALOGE_IF(error != HWC::Error::None,
1373           "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
1374           error.to_string().c_str());
1375}
1376
1377void Layer::CommonLayerSetup() {
1378  HWC::Error error = composer_->createLayer(display_params_.id,
1379                                            &hardware_composer_layer_);
1380  ALOGE_IF(error != HWC::Error::None,
1381           "Layer::CommonLayerSetup: Failed to create layer on primary "
1382           "display: %s",
1383           error.to_string().c_str());
1384  UpdateLayerSettings();
1385}
1386
1387bool Layer::CheckAndUpdateCachedBuffer(std::size_t slot, int buffer_id) {
1388  auto search = cached_buffer_map_.find(slot);
1389  if (search != cached_buffer_map_.end() && search->second == buffer_id)
1390    return true;
1391
1392  // Assign or update the buffer slot.
1393  if (buffer_id >= 0)
1394    cached_buffer_map_[slot] = buffer_id;
1395  return false;
1396}
1397
1398void Layer::Prepare() {
1399  int right, bottom, id;
1400  sp<GraphicBuffer> handle;
1401  std::size_t slot;
1402
1403  // Acquire the next buffer according to the type of source.
1404  IfAnyOf<SourceSurface, SourceBuffer>::Call(&source_, [&](auto& source) {
1405    std::tie(right, bottom, id, handle, acquire_fence_, slot) =
1406        source.Acquire();
1407  });
1408
1409  TRACE_FORMAT("Layer::Prepare|buffer_id=%d;slot=%zu|", id, slot);
1410
1411  // Update any visibility (blending, z-order) changes that occurred since
1412  // last prepare.
1413  UpdateVisibilitySettings();
1414
1415  // When a layer is first setup there may be some time before the first
1416  // buffer arrives. Setup the HWC layer as a solid color to stall for time
1417  // until the first buffer arrives. Once the first buffer arrives there will
1418  // always be a buffer for the frame even if it is old.
1419  if (!handle.get()) {
1420    if (composition_type_ == HWC::Composition::Invalid) {
1421      composition_type_ = HWC::Composition::SolidColor;
1422      composer_->setLayerCompositionType(
1423          display_params_.id, hardware_composer_layer_,
1424          composition_type_.cast<Hwc2::IComposerClient::Composition>());
1425      Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
1426      composer_->setLayerColor(display_params_.id, hardware_composer_layer_,
1427                               layer_color);
1428    } else {
1429      // The composition type is already set. Nothing else to do until a
1430      // buffer arrives.
1431    }
1432  } else {
1433    if (composition_type_ != target_composition_type_) {
1434      composition_type_ = target_composition_type_;
1435      composer_->setLayerCompositionType(
1436          display_params_.id, hardware_composer_layer_,
1437          composition_type_.cast<Hwc2::IComposerClient::Composition>());
1438    }
1439
1440    // See if the HWC cache already has this buffer.
1441    const bool cached = CheckAndUpdateCachedBuffer(slot, id);
1442    if (cached)
1443      handle = nullptr;
1444
1445    HWC::Error error{HWC::Error::None};
1446    error =
1447        composer_->setLayerBuffer(display_params_.id, hardware_composer_layer_,
1448                                  slot, handle, acquire_fence_.Get());
1449
1450    ALOGE_IF(error != HWC::Error::None,
1451             "Layer::Prepare: Error setting layer buffer: %s",
1452             error.to_string().c_str());
1453
1454    if (!surface_rect_functions_applied_) {
1455      const float float_right = right;
1456      const float float_bottom = bottom;
1457      error = composer_->setLayerSourceCrop(display_params_.id,
1458                                            hardware_composer_layer_,
1459                                            {0, 0, float_right, float_bottom});
1460
1461      ALOGE_IF(error != HWC::Error::None,
1462               "Layer::Prepare: Error setting layer source crop: %s",
1463               error.to_string().c_str());
1464
1465      surface_rect_functions_applied_ = true;
1466    }
1467  }
1468}
1469
1470void Layer::Finish(int release_fence_fd) {
1471  IfAnyOf<SourceSurface, SourceBuffer>::Call(
1472      &source_, [release_fence_fd](auto& source) {
1473        source.Finish(LocalHandle(release_fence_fd));
1474      });
1475}
1476
1477void Layer::Drop() { acquire_fence_.Close(); }
1478
1479}  // namespace dvr
1480}  // namespace android
1481