display_client.cpp revision 2251d822dac2a96aad4184a6fdc2690f0a58af7c
1#include "include/private/dvr/display_client.h" 2 3#include <cutils/native_handle.h> 4#include <log/log.h> 5#include <pdx/default_transport/client_channel.h> 6#include <pdx/default_transport/client_channel_factory.h> 7#include <pdx/status.h> 8 9#include <mutex> 10 11#include <private/dvr/display_protocol.h> 12#include <private/dvr/late_latch.h> 13#include <private/dvr/native_buffer.h> 14 15using android::pdx::ErrorStatus; 16using android::pdx::LocalHandle; 17using android::pdx::LocalChannelHandle; 18using android::pdx::Status; 19using android::pdx::Transaction; 20using android::pdx::rpc::IfAnyOf; 21 22namespace android { 23namespace dvr { 24namespace display { 25 26Surface::Surface(LocalChannelHandle channel_handle, int* error) 27 : BASE{pdx::default_transport::ClientChannel::Create( 28 std::move(channel_handle))} { 29 auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>(); 30 if (!status) { 31 ALOGE("Surface::Surface: Failed to get surface info: %s", 32 status.GetErrorMessage().c_str()); 33 Close(status.error()); 34 if (error) 35 *error = status.error(); 36 } 37 38 surface_id_ = status.get().surface_id; 39 z_order_ = status.get().z_order; 40 visible_ = status.get().visible; 41} 42 43Surface::Surface(const SurfaceAttributes& attributes, int* error) 44 : BASE{pdx::default_transport::ClientChannelFactory::Create( 45 DisplayProtocol::kClientPath), 46 kInfiniteTimeout} { 47 auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes); 48 if (!status) { 49 ALOGE("Surface::Surface: Failed to create display surface: %s", 50 status.GetErrorMessage().c_str()); 51 Close(status.error()); 52 if (error) 53 *error = status.error(); 54 } 55 56 surface_id_ = status.get().surface_id; 57 z_order_ = status.get().z_order; 58 visible_ = status.get().visible; 59} 60 61Status<void> Surface::SetVisible(bool visible) { 62 return SetAttributes( 63 {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}}); 64} 65 66Status<void> Surface::SetZOrder(int z_order) { 67 return SetAttributes( 68 {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}}); 69} 70 71Status<void> Surface::SetAttributes(const SurfaceAttributes& attributes) { 72 auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes); 73 if (!status) { 74 ALOGE( 75 "Surface::SetAttributes: Failed to set display surface " 76 "attributes: %s", 77 status.GetErrorMessage().c_str()); 78 return status.error_status(); 79 } 80 81 // Set the local cached copies of the attributes we care about from the full 82 // set of attributes sent to the display service. 83 for (const auto& attribute : attributes) { 84 const auto& key = attribute.first; 85 const auto* variant = &attribute.second; 86 bool invalid_value = false; 87 switch (key) { 88 case SurfaceAttribute::Visible: 89 invalid_value = 90 !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_); 91 break; 92 case SurfaceAttribute::ZOrder: 93 invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_); 94 break; 95 } 96 97 if (invalid_value) { 98 ALOGW( 99 "Surface::SetAttributes: Failed to set display surface " 100 "attribute %d because of incompatible type: %d", 101 key, variant->index()); 102 } 103 } 104 105 return {}; 106} 107 108Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() { 109 ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue."); 110 auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0); 111 if (!status) { 112 ALOGE("Surface::CreateQueue: Failed to create queue: %s", 113 status.GetErrorMessage().c_str()); 114 return status.error_status(); 115 } 116 117 auto producer_queue = ProducerQueue::Import(status.take()); 118 if (!producer_queue) { 119 ALOGE("Surface::CreateQueue: Failed to import producer queue!"); 120 return ErrorStatus(ENOMEM); 121 } 122 123 return {std::move(producer_queue)}; 124} 125 126Status<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(uint32_t width, 127 uint32_t height, 128 uint32_t format, 129 uint64_t usage, 130 size_t capacity) { 131 ALOGD_IF(TRACE, 132 "Surface::CreateQueue: width=%u height=%u format=%u usage=%" PRIx64 133 " capacity=%zu", 134 width, height, format, usage, capacity); 135 auto status = CreateQueue(); 136 if (!status) 137 return status.error_status(); 138 139 auto producer_queue = status.take(); 140 141 ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity); 142 for (size_t i = 0; i < capacity; i++) { 143 size_t slot; 144 const size_t kSliceCount = 1; 145 const int ret = producer_queue->AllocateBuffer(width, height, format, usage, 146 kSliceCount, &slot); 147 if (ret < 0) { 148 ALOGE( 149 "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s", 150 producer_queue->id(), strerror(-ret)); 151 return ErrorStatus(ENOMEM); 152 } 153 ALOGD_IF( 154 TRACE, 155 "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu", 156 slot, capacity); 157 } 158 159 return {std::move(producer_queue)}; 160} 161 162DisplayClient::DisplayClient(int* error) 163 : BASE(pdx::default_transport::ClientChannelFactory::Create( 164 DisplayProtocol::kClientPath), 165 kInfiniteTimeout) { 166 if (error) 167 *error = Client::error(); 168} 169 170Status<Metrics> DisplayClient::GetDisplayMetrics() { 171 return InvokeRemoteMethod<DisplayProtocol::GetMetrics>(); 172} 173 174Status<std::unique_ptr<Surface>> DisplayClient::CreateSurface( 175 const SurfaceAttributes& attributes) { 176 int error; 177 if (auto client = Surface::Create(attributes, &error)) 178 return {std::move(client)}; 179 else 180 return ErrorStatus(error); 181} 182 183Status<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer( 184 const std::string& name) { 185 auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name); 186 if (!status) { 187 ALOGE( 188 "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; " 189 "error=%s", 190 name.c_str(), status.GetErrorMessage().c_str()); 191 return status.error_status(); 192 } 193 194 auto ion_buffer = std::make_unique<IonBuffer>(); 195 auto native_buffer_handle = status.take(); 196 const int ret = native_buffer_handle.Import(ion_buffer.get()); 197 if (ret < 0) { 198 ALOGE( 199 "DisplayClient::GetNamedBuffer: Failed to import named buffer: " 200 "name=%s; error=%s", 201 name.c_str(), strerror(-ret)); 202 return ErrorStatus(-ret); 203 } 204 205 return {std::move(ion_buffer)}; 206} 207 208Status<bool> DisplayClient::IsVrAppRunning() { 209 return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>(); 210} 211 212} // namespace display 213} // namespace dvr 214} // namespace android 215