1#include <private/dvr/clock_ns.h>
2#include <private/dvr/shared_buffer_helpers.h>
3
4namespace android {
5namespace dvr {
6namespace {
7
8// We will not poll the display service for buffers more frequently than this.
9constexpr size_t kDisplayServiceTriesPerSecond = 2;
10}  // namespace
11
12CPUMappedBuffer::CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode)
13    : buffer_key_(key), usage_mode_(mode) {
14  TryMapping();
15}
16
17CPUMappedBuffer::CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer,
18                                 CPUUsageMode mode)
19    : owned_buffer_(std::move(buffer)),
20      buffer_(owned_buffer_.get()),
21      usage_mode_(mode) {
22  TryMapping();
23}
24
25CPUMappedBuffer::CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode)
26    : buffer_(buffer), usage_mode_(mode) {
27  TryMapping();
28}
29
30CPUMappedBuffer::~CPUMappedBuffer() {
31  if (IsMapped()) {
32    buffer_->Unlock();
33  }
34}
35
36void CPUMappedBuffer::TryMapping() {
37  // Do we have an IonBuffer for this shared memory object?
38  if (buffer_ == nullptr) {
39    // Has it been too long since we last connected to the display service?
40    const auto current_time_ns = GetSystemClockNs();
41    if ((current_time_ns - last_display_service_connection_ns_) <
42        (1e9 / kDisplayServiceTriesPerSecond)) {
43      // Early exit.
44      return;
45    }
46    last_display_service_connection_ns_ = current_time_ns;
47
48    // Create a display client and get the buffer.
49    auto display_client = display::DisplayClient::Create();
50    if (display_client) {
51      auto get_result = display_client->GetGlobalBuffer(buffer_key_);
52      if (get_result.ok()) {
53        owned_buffer_ = get_result.take();
54        buffer_ = owned_buffer_.get();
55      } else {
56        // The buffer has not been created yet. This is OK, we will keep
57        // retrying.
58      }
59    } else {
60      ALOGE("Unable to create display client for shared buffer access");
61    }
62  }
63
64  if (buffer_) {
65    auto usage = buffer_->usage() & ~GRALLOC_USAGE_SW_READ_MASK &
66                 ~GRALLOC_USAGE_SW_WRITE_MASK;
67
68    // Figure out the usage bits.
69    switch (usage_mode_) {
70      case CPUUsageMode::READ_OFTEN:
71        usage |= GRALLOC_USAGE_SW_READ_OFTEN;
72        break;
73      case CPUUsageMode::READ_RARELY:
74        usage |= GRALLOC_USAGE_SW_READ_RARELY;
75        break;
76      case CPUUsageMode::WRITE_OFTEN:
77        usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
78        break;
79      case CPUUsageMode::WRITE_RARELY:
80        usage |= GRALLOC_USAGE_SW_WRITE_RARELY;
81        break;
82    }
83
84    int width = static_cast<int>(buffer_->width());
85    int height = 1;
86    const auto ret = buffer_->Lock(usage, 0, 0, width, height, &address_);
87
88    if (ret < 0 || !address_) {
89      ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, address_);
90      buffer_->Unlock();
91    } else {
92      size_ = width;
93    }
94  }
95}
96
97}  // namespace dvr
98}  // namespace android
99