| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 1 | #include "include/private/dvr/display_client.h" | 
|  | 2 |  | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 3 | #include <cutils/native_handle.h> | 
| Alex Vakulenko | 4fe6058 | 2017-02-02 11:35:59 -0800 | [diff] [blame] | 4 | #include <log/log.h> | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 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_rpc.h> | 
|  | 12 | #include <private/dvr/late_latch.h> | 
|  | 13 | #include <private/dvr/native_buffer.h> | 
|  | 14 |  | 
|  | 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 |  | 
|  | 24 | SurfaceClient::SurfaceClient(LocalChannelHandle channel_handle, | 
|  | 25 | SurfaceType type) | 
|  | 26 | : Client{pdx::default_transport::ClientChannel::Create( | 
|  | 27 | std::move(channel_handle))}, | 
|  | 28 | type_(type) {} | 
|  | 29 |  | 
|  | 30 | SurfaceClient::SurfaceClient(const std::string& endpoint_path, SurfaceType type) | 
|  | 31 | : Client{pdx::default_transport::ClientChannelFactory::Create( | 
|  | 32 | endpoint_path), | 
|  | 33 | kInfiniteTimeout}, | 
|  | 34 | type_(type) {} | 
|  | 35 |  | 
|  | 36 | int SurfaceClient::GetMetadataBufferFd(LocalHandle* out_fd) { | 
|  | 37 | auto buffer_producer = GetMetadataBuffer(); | 
|  | 38 | if (!buffer_producer) | 
|  | 39 | return -ENOMEM; | 
|  | 40 |  | 
|  | 41 | *out_fd = buffer_producer->GetBlobFd(); | 
|  | 42 | return 0; | 
|  | 43 | } | 
|  | 44 |  | 
|  | 45 | std::shared_ptr<BufferProducer> SurfaceClient::GetMetadataBuffer() { | 
|  | 46 | if (!metadata_buffer_) { | 
|  | 47 | auto status = InvokeRemoteMethod<DisplayRPC::GetMetadataBuffer>(); | 
|  | 48 | if (!status) { | 
|  | 49 | ALOGE( | 
|  | 50 | "SurfaceClient::AllocateMetadataBuffer: Failed to allocate buffer: " | 
|  | 51 | "%s", | 
|  | 52 | status.GetErrorMessage().c_str()); | 
|  | 53 | return nullptr; | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | metadata_buffer_ = BufferProducer::Import(status.take()); | 
|  | 57 | } | 
|  | 58 |  | 
|  | 59 | return metadata_buffer_; | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | DisplaySurfaceClient::DisplaySurfaceClient(int width, int height, int format, | 
|  | 63 | int usage, int flags) | 
|  | 64 | : BASE(DisplayRPC::kClientPath, SurfaceTypeEnum::Normal), | 
|  | 65 | width_(width), | 
|  | 66 | height_(height), | 
|  | 67 | format_(format), | 
|  | 68 | usage_(usage), | 
|  | 69 | flags_(flags), | 
|  | 70 | z_order_(0), | 
|  | 71 | visible_(true), | 
|  | 72 | exclude_from_blur_(false), | 
|  | 73 | blur_behind_(true), | 
|  | 74 | mapped_metadata_buffer_(nullptr) { | 
|  | 75 | auto status = InvokeRemoteMethod<DisplayRPC::CreateSurface>( | 
|  | 76 | width, height, format, usage, flags); | 
|  | 77 | if (!status) { | 
|  | 78 | ALOGE( | 
|  | 79 | "DisplaySurfaceClient::DisplaySurfaceClient: Failed to create display " | 
|  | 80 | "surface: %s", | 
|  | 81 | status.GetErrorMessage().c_str()); | 
|  | 82 | Close(status.error()); | 
|  | 83 | } | 
|  | 84 | } | 
|  | 85 |  | 
|  | 86 | void DisplaySurfaceClient::SetVisible(bool visible) { | 
|  | 87 | SetAttributes({{DisplaySurfaceAttributeEnum::Visible, | 
|  | 88 | DisplaySurfaceAttributeValue{visible}}}); | 
|  | 89 | } | 
|  | 90 |  | 
|  | 91 | void DisplaySurfaceClient::SetZOrder(int z_order) { | 
|  | 92 | SetAttributes({{DisplaySurfaceAttributeEnum::ZOrder, | 
|  | 93 | DisplaySurfaceAttributeValue{z_order}}}); | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | void DisplaySurfaceClient::SetExcludeFromBlur(bool exclude_from_blur) { | 
|  | 97 | SetAttributes({{DisplaySurfaceAttributeEnum::ExcludeFromBlur, | 
|  | 98 | DisplaySurfaceAttributeValue{exclude_from_blur}}}); | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | void DisplaySurfaceClient::SetBlurBehind(bool blur_behind) { | 
|  | 102 | SetAttributes({{DisplaySurfaceAttributeEnum::BlurBehind, | 
|  | 103 | DisplaySurfaceAttributeValue{blur_behind}}}); | 
|  | 104 | } | 
|  | 105 |  | 
|  | 106 | void DisplaySurfaceClient::SetAttributes( | 
|  | 107 | const DisplaySurfaceAttributes& attributes) { | 
|  | 108 | Status<int> status = | 
|  | 109 | InvokeRemoteMethod<DisplayRPC::SetAttributes>(attributes); | 
|  | 110 | if (!status) { | 
|  | 111 | ALOGE( | 
|  | 112 | "DisplaySurfaceClient::SetAttributes: Failed to set display surface " | 
|  | 113 | "attributes: %s", | 
|  | 114 | status.GetErrorMessage().c_str()); | 
|  | 115 | return; | 
|  | 116 | } | 
|  | 117 |  | 
|  | 118 | // Set the local cached copies of the attributes we care about from the full | 
|  | 119 | // set of attributes sent to the display service. | 
|  | 120 | for (const auto& attribute : attributes) { | 
|  | 121 | const auto& key = attribute.first; | 
|  | 122 | const auto* variant = &attribute.second; | 
|  | 123 | bool invalid_value = false; | 
|  | 124 | switch (key) { | 
|  | 125 | case DisplaySurfaceAttributeEnum::Visible: | 
|  | 126 | invalid_value = | 
|  | 127 | !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_); | 
|  | 128 | break; | 
|  | 129 | case DisplaySurfaceAttributeEnum::ZOrder: | 
|  | 130 | invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_); | 
|  | 131 | break; | 
|  | 132 | case DisplaySurfaceAttributeEnum::ExcludeFromBlur: | 
|  | 133 | invalid_value = | 
|  | 134 | !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &exclude_from_blur_); | 
|  | 135 | break; | 
|  | 136 | case DisplaySurfaceAttributeEnum::BlurBehind: | 
|  | 137 | invalid_value = | 
|  | 138 | !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &blur_behind_); | 
|  | 139 | break; | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | if (invalid_value) { | 
|  | 143 | ALOGW( | 
|  | 144 | "DisplaySurfaceClient::SetAttributes: Failed to set display " | 
|  | 145 | "surface attribute '%s' because of incompatible type: %d", | 
|  | 146 | DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index()); | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 | } | 
|  | 150 |  | 
| Jiwen 'Steve' Cai | a361361 | 2017-03-08 17:41:48 -0800 | [diff] [blame] | 151 | std::shared_ptr<ProducerQueue> DisplaySurfaceClient::GetProducerQueue() { | 
|  | 152 | if (producer_queue_ == nullptr) { | 
|  | 153 | // Create producer queue through DisplayRPC | 
|  | 154 | auto status = InvokeRemoteMethod<DisplayRPC::CreateBufferQueue>(); | 
|  | 155 | if (!status) { | 
|  | 156 | ALOGE( | 
|  | 157 | "DisplaySurfaceClient::GetProducerQueue: failed to create producer " | 
|  | 158 | "queue: %s", | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 159 | status.GetErrorMessage().c_str()); | 
| Jiwen 'Steve' Cai | a361361 | 2017-03-08 17:41:48 -0800 | [diff] [blame] | 160 | return nullptr; | 
|  | 161 | } | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 162 |  | 
| Jiwen 'Steve' Cai | a361361 | 2017-03-08 17:41:48 -0800 | [diff] [blame] | 163 | producer_queue_ = | 
|  | 164 | ProducerQueue::Import<DisplaySurfaceMetadata>(status.take()); | 
|  | 165 | } | 
|  | 166 | return producer_queue_; | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 167 | } | 
|  | 168 |  | 
|  | 169 | volatile DisplaySurfaceMetadata* DisplaySurfaceClient::GetMetadataBufferPtr() { | 
|  | 170 | if (!mapped_metadata_buffer_) { | 
|  | 171 | if (auto buffer_producer = GetMetadataBuffer()) { | 
|  | 172 | void* addr = nullptr; | 
|  | 173 | const int ret = buffer_producer->GetBlobReadWritePointer( | 
|  | 174 | sizeof(DisplaySurfaceMetadata), &addr); | 
|  | 175 | if (ret < 0) { | 
|  | 176 | ALOGE( | 
|  | 177 | "DisplaySurfaceClient::GetMetadataBufferPtr: Failed to map surface " | 
|  | 178 | "metadata: %s", | 
|  | 179 | strerror(-ret)); | 
|  | 180 | return nullptr; | 
|  | 181 | } | 
|  | 182 | mapped_metadata_buffer_ = static_cast<DisplaySurfaceMetadata*>(addr); | 
|  | 183 | } | 
|  | 184 | } | 
|  | 185 |  | 
|  | 186 | return mapped_metadata_buffer_; | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | LocalChannelHandle DisplaySurfaceClient::CreateVideoMeshSurface() { | 
|  | 190 | auto status = InvokeRemoteMethod<DisplayRPC::CreateVideoMeshSurface>(); | 
|  | 191 | if (!status) { | 
|  | 192 | ALOGE( | 
|  | 193 | "DisplaySurfaceClient::CreateVideoMeshSurface: Failed to create " | 
|  | 194 | "video mesh surface: %s", | 
|  | 195 | status.GetErrorMessage().c_str()); | 
|  | 196 | } | 
|  | 197 | return status.take(); | 
|  | 198 | } | 
|  | 199 |  | 
|  | 200 | DisplayClient::DisplayClient(int* error) | 
|  | 201 | : BASE(pdx::default_transport::ClientChannelFactory::Create( | 
|  | 202 | DisplayRPC::kClientPath), | 
|  | 203 | kInfiniteTimeout) { | 
|  | 204 | if (error) | 
|  | 205 | *error = Client::error(); | 
|  | 206 | } | 
|  | 207 |  | 
|  | 208 | int DisplayClient::GetDisplayMetrics(SystemDisplayMetrics* metrics) { | 
|  | 209 | auto status = InvokeRemoteMethod<DisplayRPC::GetMetrics>(); | 
|  | 210 | if (!status) { | 
|  | 211 | ALOGE("DisplayClient::GetDisplayMetrics: Failed to get metrics: %s", | 
|  | 212 | status.GetErrorMessage().c_str()); | 
|  | 213 | return -status.error(); | 
|  | 214 | } | 
|  | 215 |  | 
|  | 216 | *metrics = status.get(); | 
|  | 217 | return 0; | 
|  | 218 | } | 
|  | 219 |  | 
|  | 220 | pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) { | 
|  | 221 | auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params); | 
|  | 222 | if (!status) { | 
|  | 223 | ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s", | 
|  | 224 | status.GetErrorMessage().c_str()); | 
|  | 225 | } | 
|  | 226 | return status; | 
|  | 227 | } | 
|  | 228 |  | 
|  | 229 | int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) { | 
|  | 230 | auto status = InvokeRemoteMethod<DisplayRPC::GetEdsCapture>(); | 
|  | 231 | if (!status) { | 
|  | 232 | ALOGE( | 
|  | 233 | "DisplayClient::GetLastFrameLateLatch: Failed to get most recent late" | 
|  | 234 | " latch: %s", | 
|  | 235 | status.GetErrorMessage().c_str()); | 
|  | 236 | return -status.error(); | 
|  | 237 | } | 
|  | 238 |  | 
|  | 239 | if (status.get().size() != sizeof(LateLatchOutput)) { | 
|  | 240 | ALOGE( | 
|  | 241 | "DisplayClient::GetLastFrameLateLatch: Error expected to receive %zu " | 
|  | 242 | "bytes but received %zu", | 
|  | 243 | sizeof(LateLatchOutput), status.get().size()); | 
|  | 244 | return -EIO; | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | *ll_out = *reinterpret_cast<const LateLatchOutput*>(status.get().data()); | 
|  | 248 | return 0; | 
|  | 249 | } | 
|  | 250 |  | 
| Jin Qian | 7480c06 | 2017-03-21 00:04:15 +0000 | [diff] [blame] | 251 | int DisplayClient::EnterVrMode() { | 
|  | 252 | auto status = InvokeRemoteMethod<DisplayRPC::EnterVrMode>(); | 
|  | 253 | if (!status) { | 
|  | 254 | ALOGE( | 
|  | 255 | "DisplayClient::EnterVrMode: Failed to set display service to Vr mode"); | 
|  | 256 | return -status.error(); | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | return 0; | 
|  | 260 | } | 
|  | 261 |  | 
|  | 262 | int DisplayClient::ExitVrMode() { | 
|  | 263 | auto status = InvokeRemoteMethod<DisplayRPC::ExitVrMode>(); | 
|  | 264 | if (!status) { | 
|  | 265 | ALOGE( | 
|  | 266 | "DisplayClient::ExitVrMode: Failed to revert display service from Vr " | 
|  | 267 | "mode"); | 
|  | 268 | return -status.error(); | 
|  | 269 | } | 
|  | 270 |  | 
|  | 271 | return 0; | 
|  | 272 | } | 
|  | 273 |  | 
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 274 | std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface( | 
|  | 275 | int width, int height, int format, int usage, int flags) { | 
|  | 276 | return DisplaySurfaceClient::Create(width, height, format, usage, flags); | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | }  // namespace dvr | 
|  | 280 | }  // namespace android |