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