display_client.cpp revision 108e84f7e6a9117b66dba000dcf16c6d8c862e16
1e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include "include/private/dvr/display_client.h"
2e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
3e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <cutils/native_handle.h>
44fe60582f314e381098f8f3bc2e39c5880e9243aAlex Vakulenko#include <log/log.h>
5e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/default_transport/client_channel.h>
6e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/default_transport/client_channel_factory.h>
7e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <pdx/status.h>
8e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
9e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <mutex>
10e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
113f82d31341f66d0c58e1ec3360ea5f528ffe0ea4Corey Tabaka#include <private/dvr/display_protocol.h>
12e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/late_latch.h>
13e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko#include <private/dvr/native_buffer.h>
14e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
152251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakausing android::pdx::ErrorStatus;
16e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalHandle;
17e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::LocalChannelHandle;
18e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Status;
19e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::Transaction;
20e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkousing android::pdx::rpc::IfAnyOf;
21e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
22e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace android {
23e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenkonamespace dvr {
242251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabakanamespace display {
25e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
262251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaSurface::Surface(LocalChannelHandle channel_handle, int* error)
272251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    : BASE{pdx::default_transport::ClientChannel::Create(
282251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          std::move(channel_handle))} {
292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = InvokeRemoteMethod<DisplayProtocol::GetSurfaceInfo>();
302251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!status) {
312251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("Surface::Surface: Failed to get surface info: %s",
32e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          status.GetErrorMessage().c_str());
332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    Close(status.error());
342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (error)
352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      *error = status.error();
36e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
37e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  surface_id_ = status.get().surface_id;
392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  z_order_ = status.get().z_order;
402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  visible_ = status.get().visible;
41e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
42e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
432251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaSurface::Surface(const SurfaceAttributes& attributes, int* error)
442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    : BASE{pdx::default_transport::ClientChannelFactory::Create(
452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               DisplayProtocol::kClientPath),
462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka           kInfiniteTimeout} {
472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = InvokeRemoteMethod<DisplayProtocol::CreateSurface>(attributes);
48e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("Surface::Surface: Failed to create display surface: %s",
502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          status.GetErrorMessage().c_str());
51e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    Close(status.error());
522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (error)
532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      *error = status.error();
54e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
55e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  surface_id_ = status.get().surface_id;
572251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  z_order_ = status.get().z_order;
582251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  visible_ = status.get().visible;
59e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
60e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> Surface::SetVisible(bool visible) {
622251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return SetAttributes(
632251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      {{SurfaceAttribute::Visible, SurfaceAttributeValue{visible}}});
64e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
65e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
662251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> Surface::SetZOrder(int z_order) {
672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return SetAttributes(
682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      {{SurfaceAttribute::ZOrder, SurfaceAttributeValue{z_order}}});
69e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
70e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<void> Surface::SetAttributes(const SurfaceAttributes& attributes) {
722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = InvokeRemoteMethod<DisplayProtocol::SetAttributes>(attributes);
73e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (!status) {
74e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    ALOGE(
752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "Surface::SetAttributes: Failed to set display surface "
76e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        "attributes: %s",
77e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        status.GetErrorMessage().c_str());
782251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return status.error_status();
79e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
80e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
81e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // Set the local cached copies of the attributes we care about from the full
82e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  // set of attributes sent to the display service.
83e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  for (const auto& attribute : attributes) {
84e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const auto& key = attribute.first;
85e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    const auto* variant = &attribute.second;
86e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    bool invalid_value = false;
87e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    switch (key) {
882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      case SurfaceAttribute::Visible:
89e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        invalid_value =
90e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko            !IfAnyOf<int32_t, int64_t, bool>::Get(variant, &visible_);
91e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      case SurfaceAttribute::ZOrder:
93e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        invalid_value = !IfAnyOf<int32_t>::Get(variant, &z_order_);
94e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko        break;
95e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
96e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
97e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    if (invalid_value) {
98e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko      ALOGW(
992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "Surface::SetAttributes: Failed to set display surface "
1002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "attribute %d because of incompatible type: %d",
1012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          key, variant->index());
102e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    }
103e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
1042251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {};
106e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
107e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1082251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<std::unique_ptr<ProducerQueue>> Surface::CreateQueue() {
1092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "Surface::CreateQueue: Creating empty queue.");
1102251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = InvokeRemoteMethod<DisplayProtocol::CreateQueue>(0);
1112251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!status) {
1122251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("Surface::CreateQueue: Failed to create queue: %s",
113e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko          status.GetErrorMessage().c_str());
1142251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return status.error_status();
115a3613612a1142c3134045f08c30a861ea43288edJiwen 'Steve' Cai  }
116e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1172251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto producer_queue = ProducerQueue::Import(status.take());
1182251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!producer_queue) {
1192251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE("Surface::CreateQueue: Failed to import producer queue!");
1202251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return ErrorStatus(ENOMEM);
121e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
122e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1232251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {std::move(producer_queue)};
124e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
125e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
126108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik WagenaarStatus<std::unique_ptr<ProducerQueue>> Surface::CreateQueue(
127108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar    uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
128108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar    uint64_t usage, size_t capacity) {
1292251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE,
130108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar           "Surface::CreateQueue: width=%u height=%u layer_count=%u format=%u "
131108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar           "usage=%" PRIx64 " capacity=%zu",
132108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar           width, height, layer_count, format, usage, capacity);
1332251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = CreateQueue();
1342251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (!status)
1352251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return status.error_status();
1362251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1372251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto producer_queue = status.take();
1382251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1392251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
1402251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  for (size_t i = 0; i < capacity; i++) {
1412251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    size_t slot;
142108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar    const int ret = producer_queue->AllocateBuffer(width, height, layer_count,
143108e84f7e6a9117b66dba000dcf16c6d8c862e16Hendrik Wagenaar                                                   format, usage, &slot);
1442251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    if (ret < 0) {
1452251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      ALOGE(
1462251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
1472251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka          producer_queue->id(), strerror(-ret));
1482251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka      return ErrorStatus(ENOMEM);
1492251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    }
1502251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGD_IF(
1512251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        TRACE,
1522251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
1532251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        slot, capacity);
154e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  }
1552251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
1562251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {std::move(producer_queue)};
157e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
158e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
159e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex VakulenkoDisplayClient::DisplayClient(int* error)
160e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    : BASE(pdx::default_transport::ClientChannelFactory::Create(
1612251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka               DisplayProtocol::kClientPath),
162e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko           kInfiniteTimeout) {
163e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko  if (error)
164e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko    *error = Client::error();
165e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
166e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1672251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<Metrics> DisplayClient::GetDisplayMetrics() {
1682251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return InvokeRemoteMethod<DisplayProtocol::GetMetrics>();
169e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
170e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1712251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<std::unique_ptr<Surface>> DisplayClient::CreateSurface(
1722251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    const SurfaceAttributes& attributes) {
1732251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  int error;
1742251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (auto client = Surface::Create(attributes, &error))
1752251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return {std::move(client)};
1762251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  else
1772251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return ErrorStatus(error);
178e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}
179e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko
1802251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<std::unique_ptr<IonBuffer>> DisplayClient::GetNamedBuffer(
181eaa5522feac452703a0836310047d4b15702487dHendrik Wagenaar    const std::string& name) {
1822251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto status = InvokeRemoteMethod<DisplayProtocol::GetNamedBuffer>(name);
18310e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar  if (!status) {
18410e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar    ALOGE(
1852251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "DisplayClient::GetNamedBuffer: Failed to get named buffer: name=%s; "
186eaa5522feac452703a0836310047d4b15702487dHendrik Wagenaar        "error=%s",
187eaa5522feac452703a0836310047d4b15702487dHendrik Wagenaar        name.c_str(), status.GetErrorMessage().c_str());
1882251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return status.error_status();
18910e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar  }
19010e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar
191eaa5522feac452703a0836310047d4b15702487dHendrik Wagenaar  auto ion_buffer = std::make_unique<IonBuffer>();
1922251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  auto native_buffer_handle = status.take();
1932251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  const int ret = native_buffer_handle.Import(ion_buffer.get());
1942251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  if (ret < 0) {
1952251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    ALOGE(
1962251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "DisplayClient::GetNamedBuffer: Failed to import named buffer: "
1972251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        "name=%s; error=%s",
1982251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka        name.c_str(), strerror(-ret));
1992251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka    return ErrorStatus(-ret);
2002251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  }
2012251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka
2022251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return {std::move(ion_buffer)};
20310e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar}
20410e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar
2052251d822dac2a96aad4184a6fdc2690f0a58af7cCorey TabakaStatus<bool> DisplayClient::IsVrAppRunning() {
2062251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka  return InvokeRemoteMethod<DisplayProtocol::IsVrAppRunning>();
207b7c8a4bd8131ce18fb4ab4ee986c3b6b1ed27ad5Albert Chaulk}
20810e68eb8aa4db8b6f8cfbf2c3754e2677d7bf848Hendrik Wagenaar
2092251d822dac2a96aad4184a6fdc2690f0a58af7cCorey Tabaka}  // namespace display
210e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace dvr
211e4eec20f6263f4a42ae462456f60ea6c4518bb0aAlex Vakulenko}  // namespace android
212