1 #ifndef ANDROID_DVR_SHARED_BUFFER_HELPERS_H_ 2 #define ANDROID_DVR_SHARED_BUFFER_HELPERS_H_ 3 4 #include <assert.h> 5 #include <tuple> 6 7 #include <libbroadcastring/broadcast_ring.h> 8 #include <private/dvr/display_client.h> 9 10 namespace android { 11 namespace dvr { 12 13 // The buffer usage type for mapped shared buffers. 14 enum class CPUUsageMode { READ_OFTEN, READ_RARELY, WRITE_OFTEN, WRITE_RARELY }; 15 16 // Holds the memory for the mapped shared buffer. Unlocks and releases the 17 // underlying IonBuffer in destructor. 18 class CPUMappedBuffer { 19 public: 20 // This constructor will create a display client and get the buffer from it. 21 CPUMappedBuffer(DvrGlobalBufferKey key, CPUUsageMode mode); 22 23 // If you already have the IonBuffer, use this. It will take ownership. 24 CPUMappedBuffer(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode); 25 26 // Use this if you do not want to take ownership. 27 CPUMappedBuffer(IonBuffer* buffer, CPUUsageMode mode); 28 29 ~CPUMappedBuffer(); 30 31 // Getters. Size()32 size_t Size() const { return size_; } Address()33 void* Address() const { return address_; } IsMapped()34 bool IsMapped() const { return Address() != nullptr; } 35 36 // Attempt mapping this buffer to the CPU addressable space. 37 // This will create a display client and see if the buffer exists. 38 // If the buffer has not been setup yet, you will need to try again later. 39 void TryMapping(); 40 41 protected: 42 // The memory area if we managed to map it. 43 size_t size_ = 0; 44 void* address_ = nullptr; 45 46 // If we are polling the display client, the buffer key here. 47 DvrGlobalBufferKey buffer_key_; 48 49 // If we just own the IonBuffer outright, it's here. 50 std::unique_ptr<IonBuffer> owned_buffer_ = nullptr; 51 52 // The last time we connected to the display service. 53 int64_t last_display_service_connection_ns_ = 0; 54 55 // If we do not own the IonBuffer, it's here 56 IonBuffer* buffer_ = nullptr; 57 58 // The usage mode. 59 CPUUsageMode usage_mode_ = CPUUsageMode::READ_OFTEN; 60 }; 61 62 // Represents a broadcast ring inside a mapped shared memory buffer. 63 // If has the same set of constructors as CPUMappedBuffer. 64 // The template argument is the concrete BroadcastRing class that this buffer 65 // holds. 66 template <class RingType> 67 class CPUMappedBroadcastRing : public CPUMappedBuffer { 68 public: CPUMappedBroadcastRing(DvrGlobalBufferKey key,CPUUsageMode mode)69 CPUMappedBroadcastRing(DvrGlobalBufferKey key, CPUUsageMode mode) 70 : CPUMappedBuffer(key, mode) {} 71 CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer,CPUUsageMode mode)72 CPUMappedBroadcastRing(std::unique_ptr<IonBuffer> buffer, CPUUsageMode mode) 73 : CPUMappedBuffer(std::move(buffer), mode) {} 74 CPUMappedBroadcastRing(IonBuffer * buffer,CPUUsageMode mode)75 CPUMappedBroadcastRing(IonBuffer* buffer, CPUUsageMode mode) 76 : CPUMappedBuffer(buffer, mode) {} 77 78 // Helper function for publishing records in the ring. Publish(const typename RingType::Record & record)79 void Publish(const typename RingType::Record& record) { 80 assert((usage_mode_ == CPUUsageMode::WRITE_OFTEN) || 81 (usage_mode_ == CPUUsageMode::WRITE_RARELY)); 82 83 auto ring = Ring(); 84 if (ring) { 85 ring->Put(record); 86 } 87 } 88 89 // Helper function for getting records from the ring. 90 // Returns true if we were able to retrieve the latest. GetNewest(typename RingType::Record * record)91 bool GetNewest(typename RingType::Record* record) { 92 assert((usage_mode_ == CPUUsageMode::READ_OFTEN) || 93 (usage_mode_ == CPUUsageMode::READ_RARELY)); 94 95 auto ring = Ring(); 96 if (ring) { 97 return ring->GetNewest(&sequence_, record); 98 } 99 100 return false; 101 } 102 103 // Try obtaining the ring. If the named buffer has not been created yet, it 104 // will return nullptr. Ring()105 RingType* Ring() { 106 // No ring created yet? 107 if (ring_ == nullptr) { 108 // Not mapped the memory yet? 109 if (IsMapped() == false) { 110 TryMapping(); 111 } 112 113 // If have the memory mapped, allocate the ring. 114 if (IsMapped()) { 115 switch (usage_mode_) { 116 case CPUUsageMode::READ_OFTEN: 117 case CPUUsageMode::READ_RARELY: { 118 RingType ring; 119 bool import_ok; 120 std::tie(ring, import_ok) = RingType::Import(address_, size_); 121 if (import_ok) { 122 ring_ = std::make_unique<RingType>(ring); 123 } 124 } break; 125 case CPUUsageMode::WRITE_OFTEN: 126 case CPUUsageMode::WRITE_RARELY: 127 ring_ = 128 std::make_unique<RingType>(RingType::Create(address_, size_)); 129 break; 130 } 131 } 132 } 133 134 return ring_.get(); 135 } 136 137 protected: 138 std::unique_ptr<RingType> ring_ = nullptr; 139 140 uint32_t sequence_ = 0; 141 }; 142 143 } // namespace dvr 144 } // namespace android 145 146 #endif // ANDROID_DVR_SHARED_BUFFER_HELPERS_H_ 147