1822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
2822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
3822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
4822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#include <assert.h>
5822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#include <tuple>
6822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
7822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#include <libbroadcastring/broadcast_ring.h>
8822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#include <private/dvr/display_client.h>
9822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
10822b710a714c342dda0087f594c8ababa6630f44Okan Arikannamespace android {
11822b710a714c342dda0087f594c8ababa6630f44Okan Arikannamespace dvr {
12822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
13822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// The buffer usage type for mapped shared buffers.
14822b710a714c342dda0087f594c8ababa6630f44Okan Arikanenum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY };
15822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
16822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// Holds the memory for the mapped shared buffer. Unlocks and releases the
17822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// underlying IonBuffer in destructor.
18822b710a714c342dda0087f594c8ababa6630f44Okan Arikanclass CPUMappedBuffer {
19822b710a714c342dda0087f594c8ababa6630f44Okan Arikan public:
20822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // This constructor will create a display client and get the buffer from it.
21822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode);
22822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
23822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // If you already have the IonBuffer, use this. It will take ownership.
24822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode);
25822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
26822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Use this if you do not want to take ownership.
27822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode);
28822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
29822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  ~CPUMappedBuffer();
30822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
31822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Getters.
32822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  size_t Size() const { return size_; }
33822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  void* Address() const { return address_; }
34822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  bool IsMapped() const { return Address() != nullptr; }
35822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
36822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Attempt mapping this buffer to the CPU addressable space.
37822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // This will create a display client and see if the buffer exists.
38822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // If the buffer has not been setup yet, you will need to try again later.
39822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  void TryMapping();
40822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
41822b710a714c342dda0087f594c8ababa6630f44Okan Arikan protected:
42822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // The memory area if we managed to map it.
43822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  size_t size_ = 0;
44822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  void* address_ = nullptr;
45822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
46822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // If we are polling the display client, the buffer key here.
47822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  DvrGlobalBufferKey buffer_key_;
48822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
49822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // If we just own the IonBuffer outright, it's here.
50822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  std::unique_ptr<IonBuffer> owned_buffer_ = nullptr;
51822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
524a3863d067003a4428582a8484040cad09f6a29dOkan Arikan  // The last time we connected to the display service.
534a3863d067003a4428582a8484040cad09f6a29dOkan Arikan  int64_t last_display_service_connection_ns_ = 0;
544a3863d067003a4428582a8484040cad09f6a29dOkan Arikan
55822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // If we do not own the IonBuffer, it's here
56822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  IonBuffer* buffer_ = nullptr;
57822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
58822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // The usage mode.
59822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN;
60822b710a714c342dda0087f594c8ababa6630f44Okan Arikan};
61822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
62822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// Represents a broadcast ring inside a mapped shared memory buffer.
63822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// If has the same set of constructors as CPUMappedBuffer.
64822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// The template argument is the concrete BroadcastRing class that this buffer
65822b710a714c342dda0087f594c8ababa6630f44Okan Arikan// holds.
66822b710a714c342dda0087f594c8ababa6630f44Okan Arikantemplate <class RingType>
67822b710a714c342dda0087f594c8ababa6630f44Okan Arikanclass CPUMappedBroadcastRing : public CPUMappedBuffer {
68822b710a714c342dda0087f594c8ababa6630f44Okan Arikan public:
69822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode)
70822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      : CPUMappedBuffer(key, mode) {}
71822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
72822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode)
73822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      : CPUMappedBuffer(std::move(buffer), mode) {}
74822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
75822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode)
76822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      : CPUMappedBuffer(buffer, mode) {}
77822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
78822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Helper function for publishing records in the ring.
79822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  void Publish(const typename RingType::Record& record) {
80822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) ||
81822b710a714c342dda0087f594c8ababa6630f44Okan Arikan           (usage_mode_ == CPUUsageMode::WRITE_RARELY));
82822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
83822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    auto ring = Ring();
84822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    if (ring) {
85822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      ring->Put(record);
86822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    }
87822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  }
88822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
89822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Helper function for getting records from the ring.
90822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Returns true if we were able to retrieve the latest.
91822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  bool GetNewest(typename RingType::Record* record) {
92822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    assert((usage_mode_ == CPUUsageMode::READ_OFTEN) ||
93822b710a714c342dda0087f594c8ababa6630f44Okan Arikan           (usage_mode_ == CPUUsageMode::READ_RARELY));
94822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
95822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    auto ring = Ring();
96822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    if (ring) {
97822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      return ring->GetNewest(&sequence_, record);
98822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    }
99822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
100822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    return false;
101822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  }
102822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
103822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // Try obtaining the ring. If the named buffer has not been created yet, it
104822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  // will return nullptr.
105822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  RingType* Ring() {
1062a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan    // No ring created yet?
1072a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan    if (ring_ == nullptr) {
1082a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan      // Not mapped the memory yet?
1092a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan      if (IsMapped() == false) {
1102a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan        TryMapping();
1112a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan      }
112822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
1132a4d63ce1737705fff6def88e68b2e537db9074cOkan Arikan      // If have the memory mapped, allocate the ring.
114822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      if (IsMapped()) {
115822b710a714c342dda0087f594c8ababa6630f44Okan Arikan        switch (usage_mode_) {
116822b710a714c342dda0087f594c8ababa6630f44Okan Arikan          case CPUUsageMode::READ_OFTEN:
117822b710a714c342dda0087f594c8ababa6630f44Okan Arikan          case CPUUsageMode::READ_RARELY: {
118822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            RingType ring;
119822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            bool import_ok;
120822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            std::tie(ring, import_ok) = RingType::Import(address_, size_);
121822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            if (import_ok) {
122822b710a714c342dda0087f594c8ababa6630f44Okan Arikan              ring_ = std::make_unique<RingType>(ring);
123822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            }
124822b710a714c342dda0087f594c8ababa6630f44Okan Arikan          } break;
125822b710a714c342dda0087f594c8ababa6630f44Okan Arikan          case CPUUsageMode::WRITE_OFTEN:
126822b710a714c342dda0087f594c8ababa6630f44Okan Arikan          case CPUUsageMode::WRITE_RARELY:
127822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            ring_ =
128822b710a714c342dda0087f594c8ababa6630f44Okan Arikan                std::make_unique<RingType>(RingType::Create(address_, size_));
129822b710a714c342dda0087f594c8ababa6630f44Okan Arikan            break;
130822b710a714c342dda0087f594c8ababa6630f44Okan Arikan        }
131822b710a714c342dda0087f594c8ababa6630f44Okan Arikan      }
132822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    }
133822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
134822b710a714c342dda0087f594c8ababa6630f44Okan Arikan    return ring_.get();
135822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  }
136822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
137822b710a714c342dda0087f594c8ababa6630f44Okan Arikan protected:
138822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  std::unique_ptr<RingType> ring_ = nullptr;
139822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
140822b710a714c342dda0087f594c8ababa6630f44Okan Arikan  uint32_t sequence_ = 0;
141822b710a714c342dda0087f594c8ababa6630f44Okan Arikan};
142822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
143822b710a714c342dda0087f594c8ababa6630f44Okan Arikan}  // namespace dvr
144822b710a714c342dda0087f594c8ababa6630f44Okan Arikan}  // namespace android
145822b710a714c342dda0087f594c8ababa6630f44Okan Arikan
146822b710a714c342dda0087f594c8ababa6630f44Okan Arikan#endif  // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_
147