blob: 582fed3a4a5f32b7d759a24b69ad9c0e7028ac15 [file] [log] [blame]
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08001#include "display_service.h"
2
Hendrik Wagenaareaa55222017-04-06 10:56:23 -07003#include <unistd.h>
Corey Tabaka0b485c92017-05-19 12:02:58 -07004
5#include <algorithm>
6#include <sstream>
7#include <string>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -08008#include <vector>
9
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -070010#include <android-base/file.h>
11#include <android-base/properties.h>
Corey Tabaka2251d822017-04-20 16:04:07 -070012#include <dvr/dvr_display_types.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080013#include <pdx/default_transport/service_endpoint.h>
14#include <pdx/rpc/remote_method.h>
Corey Tabaka99c2d732017-06-07 17:54:33 -070015#include <private/android_filesystem_config.h>
Corey Tabaka3f82d312017-04-20 14:42:08 -070016#include <private/dvr/display_protocol.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080017#include <private/dvr/numeric.h>
Corey Tabaka99c2d732017-06-07 17:54:33 -070018#include <private/dvr/trusted_uids.h>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080019#include <private/dvr/types.h>
20
mamik913cc132019-09-13 14:58:43 -070021#include "DisplayHardware/DisplayIdentification.h"
22
Corey Tabaka2251d822017-04-20 16:04:07 -070023using android::dvr::display::DisplayProtocol;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080024using android::pdx::Channel;
Corey Tabaka2251d822017-04-20 16:04:07 -070025using android::pdx::ErrorStatus;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080026using android::pdx::Message;
Corey Tabaka2251d822017-04-20 16:04:07 -070027using android::pdx::Status;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080028using android::pdx::default_transport::Endpoint;
29using android::pdx::rpc::DispatchRemoteMethod;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080030
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -070031namespace {
32
33const char kDvrLensMetricsProperty[] = "ro.dvr.lens_metrics";
34const char kDvrDeviceMetricsProperty[] = "ro.dvr.device_metrics";
35const char kDvrDeviceConfigProperty[] = "ro.dvr.device_configuration";
36
37} // namespace
38
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080039namespace android {
40namespace dvr {
41
Corey Tabaka2251d822017-04-20 16:04:07 -070042DisplayService::DisplayService(Hwc2::Composer* hidl,
Steven Thomas6e8f7062017-11-22 14:15:29 -080043 hwc2_display_t primary_display_id,
Corey Tabaka2251d822017-04-20 16:04:07 -070044 RequestDisplayCallback request_display_callback)
45 : BASE("DisplayService",
Steven Thomasd7f49c52017-07-26 18:48:28 -070046 Endpoint::Create(display::DisplayProtocol::kClientPath)) {
Steven Thomas6e8f7062017-11-22 14:15:29 -080047 hardware_composer_.Initialize(
48 hidl, primary_display_id, request_display_callback);
Stephen Kiazyk016e5e32017-02-21 17:09:22 -080049}
50
51bool DisplayService::IsInitialized() const {
52 return BASE::IsInitialized() && hardware_composer_.IsInitialized();
53}
Alex Vakulenkoa8a92782017-01-27 14:41:57 -080054
Corey Tabaka2251d822017-04-20 16:04:07 -070055std::string DisplayService::DumpState(size_t /*max_length*/) {
Corey Tabaka0b485c92017-05-19 12:02:58 -070056 std::ostringstream stream;
57
58 auto surfaces = GetDisplaySurfaces();
59 std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
60 return a->surface_id() < b->surface_id();
61 });
62
63 stream << "Application Surfaces:" << std::endl;
64
65 size_t count = 0;
66 for (const auto& surface : surfaces) {
67 if (surface->surface_type() == SurfaceType::Application) {
68 stream << "Surface " << count++ << ":";
69 stream << " surface_id=" << surface->surface_id()
70 << " process_id=" << surface->process_id()
71 << " user_id=" << surface->user_id()
72 << " visible=" << surface->visible()
73 << " z_order=" << surface->z_order();
74
75 stream << " queue_ids=";
76 auto queue_ids = surface->GetQueueIds();
77 std::sort(queue_ids.begin(), queue_ids.end());
78 for (int32_t id : queue_ids) {
79 if (id != queue_ids[0])
80 stream << ",";
81 stream << id;
82 }
83 stream << std::endl;
84 }
85 }
86 stream << std::endl;
87
88 stream << "Direct Surfaces:" << std::endl;
89
90 count = 0;
91 for (const auto& surface : surfaces) {
92 if (surface->surface_type() == SurfaceType::Direct) {
93 stream << "Surface " << count++ << ":";
94 stream << " surface_id=" << surface->surface_id()
95 << " process_id=" << surface->process_id()
96 << " user_id=" << surface->user_id()
97 << " visible=" << surface->visible()
98 << " z_order=" << surface->z_order();
99
100 stream << " queue_ids=";
101 auto queue_ids = surface->GetQueueIds();
102 std::sort(queue_ids.begin(), queue_ids.end());
103 for (int32_t id : queue_ids) {
104 if (id != queue_ids[0])
105 stream << ",";
106 stream << id;
107 }
108 stream << std::endl;
109 }
110 }
111 stream << std::endl;
112
113 stream << hardware_composer_.Dump();
114 return stream.str();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800115}
116
Corey Tabaka2251d822017-04-20 16:04:07 -0700117void DisplayService::OnChannelClose(pdx::Message& message,
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800118 const std::shared_ptr<Channel>& channel) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700119 if (auto surface = std::static_pointer_cast<DisplaySurface>(channel)) {
120 surface->OnSetAttributes(message,
121 {{display::SurfaceAttribute::Visible,
122 display::SurfaceAttributeValue{false}}});
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800123 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800124}
125
126// First-level dispatch for display service messages. Directly handles messages
127// that are independent of the display surface (metrics, creation) and routes
128// surface-specific messages to the per-instance handlers.
Corey Tabaka2251d822017-04-20 16:04:07 -0700129Status<void> DisplayService::HandleMessage(pdx::Message& message) {
130 ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
Corey Tabakab3732f02017-09-16 00:58:54 -0700131 ATRACE_NAME("DisplayService::HandleMessage");
132
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800133 switch (message.GetOp()) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700134 case DisplayProtocol::GetMetrics::Opcode:
135 DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800136 *this, &DisplayService::OnGetMetrics, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700137 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800138
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -0700139 case DisplayProtocol::GetConfigurationData::Opcode:
140 DispatchRemoteMethod<DisplayProtocol::GetConfigurationData>(
141 *this, &DisplayService::OnGetConfigurationData, message);
142 return {};
143
mamik94e91f62019-08-19 09:11:33 -0700144 case DisplayProtocol::GetDisplayIdentificationPort::Opcode:
145 DispatchRemoteMethod<DisplayProtocol::GetDisplayIdentificationPort>(
146 *this, &DisplayService::OnGetDisplayIdentificationPort, message);
147 return {};
148
Corey Tabaka2251d822017-04-20 16:04:07 -0700149 case DisplayProtocol::CreateSurface::Opcode:
150 DispatchRemoteMethod<DisplayProtocol::CreateSurface>(
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800151 *this, &DisplayService::OnCreateSurface, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700152 return {};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800153
Corey Tabaka99c2d732017-06-07 17:54:33 -0700154 case DisplayProtocol::SetupGlobalBuffer::Opcode:
155 DispatchRemoteMethod<DisplayProtocol::SetupGlobalBuffer>(
156 *this, &DisplayService::OnSetupGlobalBuffer, message);
157 return {};
158
159 case DisplayProtocol::DeleteGlobalBuffer::Opcode:
160 DispatchRemoteMethod<DisplayProtocol::DeleteGlobalBuffer>(
161 *this, &DisplayService::OnDeleteGlobalBuffer, message);
162 return {};
163
Okan Arikan36d23802017-05-15 15:20:39 -0700164 case DisplayProtocol::GetGlobalBuffer::Opcode:
165 DispatchRemoteMethod<DisplayProtocol::GetGlobalBuffer>(
166 *this, &DisplayService::OnGetGlobalBuffer, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700167 return {};
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700168
Corey Tabaka2251d822017-04-20 16:04:07 -0700169 case DisplayProtocol::IsVrAppRunning::Opcode:
170 DispatchRemoteMethod<DisplayProtocol::IsVrAppRunning>(
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400171 *this, &DisplayService::IsVrAppRunning, message);
Alex Vakulenkof0a7bd02017-03-31 18:06:19 -0700172 return {};
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400173
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800174 // Direct the surface specific messages to the surface instance.
Corey Tabaka2251d822017-04-20 16:04:07 -0700175 case DisplayProtocol::SetAttributes::Opcode:
176 case DisplayProtocol::CreateQueue::Opcode:
177 case DisplayProtocol::GetSurfaceInfo::Opcode:
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800178 return HandleSurfaceMessage(message);
179
180 default:
181 return Service::HandleMessage(message);
182 }
183}
184
Corey Tabaka2251d822017-04-20 16:04:07 -0700185Status<display::Metrics> DisplayService::OnGetMetrics(
186 pdx::Message& /*message*/) {
Steven Thomasbfe46a02018-02-16 14:27:35 -0800187 const auto& params = hardware_composer_.GetPrimaryDisplayParams();
188 return {{static_cast<uint32_t>(params.width),
189 static_cast<uint32_t>(params.height),
190 static_cast<uint32_t>(params.dpi.x),
191 static_cast<uint32_t>(params.dpi.y),
192 static_cast<uint32_t>(params.vsync_period_ns),
Corey Tabaka2251d822017-04-20 16:04:07 -0700193 0,
194 0,
195 0,
196 0.0,
197 {},
198 {}}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800199}
200
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -0700201pdx::Status<std::string> DisplayService::OnGetConfigurationData(
202 pdx::Message& /*message*/, display::ConfigFileType config_type) {
203 std::string property_name;
mamik913cc132019-09-13 14:58:43 -0700204 DisplayIdentificationData display_identification_data;
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -0700205 switch (config_type) {
206 case display::ConfigFileType::kLensMetrics:
207 property_name = kDvrLensMetricsProperty;
208 break;
209 case display::ConfigFileType::kDeviceMetrics:
210 property_name = kDvrDeviceMetricsProperty;
211 break;
212 case display::ConfigFileType::kDeviceConfiguration:
213 property_name = kDvrDeviceConfigProperty;
214 break;
mamika08194b2019-07-25 13:07:21 -0700215 case display::ConfigFileType::kDeviceEdid:
mamik913cc132019-09-13 14:58:43 -0700216 display_identification_data =
217 hardware_composer_.GetCurrentDisplayIdentificationData();
218 if (display_identification_data.size() == 0) {
mamika08194b2019-07-25 13:07:21 -0700219 return ErrorStatus(ENOENT);
220 }
mamik913cc132019-09-13 14:58:43 -0700221 return std::string(display_identification_data.begin(),
222 display_identification_data.end());
Hendrik Wagenaarbcb03d02017-05-23 14:59:08 -0700223 default:
224 return ErrorStatus(EINVAL);
225 }
226 std::string file_path = base::GetProperty(property_name, "");
227 if (file_path.empty()) {
228 return ErrorStatus(ENOENT);
229 }
230
231 std::string data;
232 if (!base::ReadFileToString(file_path, &data)) {
233 return ErrorStatus(errno);
234 }
235
236 return std::move(data);
237}
238
mamik94e91f62019-08-19 09:11:33 -0700239pdx::Status<uint8_t> DisplayService::OnGetDisplayIdentificationPort(
240 pdx::Message& /*message*/) {
mamik913cc132019-09-13 14:58:43 -0700241 return hardware_composer_.GetCurrentDisplayPort();
mamik94e91f62019-08-19 09:11:33 -0700242}
243
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800244// Creates a new DisplaySurface and associates it with this channel. This may
245// only be done once per channel.
Corey Tabaka2251d822017-04-20 16:04:07 -0700246Status<display::SurfaceInfo> DisplayService::OnCreateSurface(
247 pdx::Message& message, const display::SurfaceAttributes& attributes) {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800248 // A surface may only be created once per channel.
249 if (message.GetChannel())
Corey Tabaka2251d822017-04-20 16:04:07 -0700250 return ErrorStatus(EINVAL);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800251
252 ALOGI_IF(TRACE, "DisplayService::OnCreateSurface: cid=%d",
253 message.GetChannelId());
254
255 // Use the channel id as the unique surface id.
256 const int surface_id = message.GetChannelId();
257 const int process_id = message.GetProcessId();
Corey Tabaka2251d822017-04-20 16:04:07 -0700258 const int user_id = message.GetEffectiveUserId();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800259
260 ALOGI_IF(TRACE,
Corey Tabaka2251d822017-04-20 16:04:07 -0700261 "DisplayService::OnCreateSurface: surface_id=%d process_id=%d",
262 surface_id, process_id);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800263
Corey Tabaka2251d822017-04-20 16:04:07 -0700264 auto surface_status =
265 DisplaySurface::Create(this, surface_id, process_id, user_id, attributes);
266 if (!surface_status) {
267 ALOGE("DisplayService::OnCreateSurface: Failed to create surface: %s",
268 surface_status.GetErrorMessage().c_str());
269 return ErrorStatus(surface_status.error());
270 }
Corey Tabaka00d9bb32017-08-16 19:59:48 -0700271 auto surface = surface_status.take();
272 message.SetChannel(surface);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800273
Corey Tabaka00d9bb32017-08-16 19:59:48 -0700274 // Update the surface with the attributes supplied with the create call. For
275 // application surfaces this has the side effect of notifying the display
276 // manager of the new surface. For direct surfaces, this may trigger a mode
277 // change, depending on the value of the visible attribute.
278 surface->OnSetAttributes(message, attributes);
Corey Tabaka2251d822017-04-20 16:04:07 -0700279
Corey Tabaka00d9bb32017-08-16 19:59:48 -0700280 return {{surface->surface_id(), surface->visible(), surface->z_order()}};
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800281}
282
Corey Tabaka2251d822017-04-20 16:04:07 -0700283void DisplayService::SurfaceUpdated(SurfaceType surface_type,
284 display::SurfaceUpdateFlags update_flags) {
285 ALOGD_IF(TRACE, "DisplayService::SurfaceUpdated: update_flags=%x",
286 update_flags.value());
287 if (update_flags.value() != 0) {
288 if (surface_type == SurfaceType::Application)
289 NotifyDisplayConfigurationUpdate();
290 else
291 UpdateActiveDisplaySurfaces();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800292 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800293}
294
Corey Tabaka99c2d732017-06-07 17:54:33 -0700295pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnSetupGlobalBuffer(
296 pdx::Message& message, DvrGlobalBufferKey key, size_t size,
297 uint64_t usage) {
298 const int user_id = message.GetEffectiveUserId();
299 const bool trusted = user_id == AID_ROOT || IsTrustedUid(user_id);
300
301 if (!trusted) {
302 ALOGE(
303 "DisplayService::OnSetupGlobalBuffer: Permission denied for user_id=%d",
304 user_id);
305 return ErrorStatus(EPERM);
306 }
307 return SetupGlobalBuffer(key, size, usage);
308}
309
310pdx::Status<void> DisplayService::OnDeleteGlobalBuffer(pdx::Message& message,
311 DvrGlobalBufferKey key) {
312 const int user_id = message.GetEffectiveUserId();
313 const bool trusted = (user_id == AID_ROOT) || IsTrustedUid(user_id);
314
315 if (!trusted) {
316 ALOGE(
317 "DisplayService::OnDeleteGlobalBuffer: Permission denied for "
318 "user_id=%d",
319 user_id);
320 return ErrorStatus(EPERM);
321 }
322 return DeleteGlobalBuffer(key);
323}
324
Okan Arikan36d23802017-05-15 15:20:39 -0700325pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetGlobalBuffer(
326 pdx::Message& /* message */, DvrGlobalBufferKey key) {
327 ALOGD_IF(TRACE, "DisplayService::OnGetGlobalBuffer: key=%d", key);
328 auto global_buffer = global_buffers_.find(key);
329 if (global_buffer != global_buffers_.end())
330 return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
Corey Tabaka2251d822017-04-20 16:04:07 -0700331 else
332 return pdx::ErrorStatus(EINVAL);
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700333}
334
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800335// Calls the message handler for the DisplaySurface associated with this
336// channel.
Corey Tabaka2251d822017-04-20 16:04:07 -0700337Status<void> DisplayService::HandleSurfaceMessage(pdx::Message& message) {
338 auto surface = std::static_pointer_cast<DisplaySurface>(message.GetChannel());
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800339 ALOGW_IF(!surface,
340 "DisplayService::HandleSurfaceMessage: surface is nullptr!");
341
342 if (surface)
343 return surface->HandleMessage(message);
344 else
Corey Tabaka2251d822017-04-20 16:04:07 -0700345 return ErrorStatus(EINVAL);
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800346}
347
348std::shared_ptr<DisplaySurface> DisplayService::GetDisplaySurface(
349 int surface_id) const {
350 return std::static_pointer_cast<DisplaySurface>(GetChannel(surface_id));
351}
352
353std::vector<std::shared_ptr<DisplaySurface>>
354DisplayService::GetDisplaySurfaces() const {
355 return GetChannels<DisplaySurface>();
356}
357
Corey Tabaka2251d822017-04-20 16:04:07 -0700358std::vector<std::shared_ptr<DirectDisplaySurface>>
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800359DisplayService::GetVisibleDisplaySurfaces() const {
Corey Tabaka2251d822017-04-20 16:04:07 -0700360 std::vector<std::shared_ptr<DirectDisplaySurface>> visible_surfaces;
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800361
362 ForEachDisplaySurface(
Corey Tabaka2251d822017-04-20 16:04:07 -0700363 SurfaceType::Direct,
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800364 [&](const std::shared_ptr<DisplaySurface>& surface) mutable {
Corey Tabaka2251d822017-04-20 16:04:07 -0700365 if (surface->visible()) {
366 visible_surfaces.push_back(
367 std::static_pointer_cast<DirectDisplaySurface>(surface));
368 surface->ClearUpdate();
369 }
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800370 });
371
372 return visible_surfaces;
373}
374
Steven Thomas050b2c82017-03-06 11:45:16 -0800375void DisplayService::UpdateActiveDisplaySurfaces() {
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800376 auto visible_surfaces = GetVisibleDisplaySurfaces();
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800377 ALOGD_IF(TRACE,
378 "DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
379 visible_surfaces.size());
Steven Thomas050b2c82017-03-06 11:45:16 -0800380 hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800381}
382
Okan Arikan36d23802017-05-15 15:20:39 -0700383pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupGlobalBuffer(
384 DvrGlobalBufferKey key, size_t size, uint64_t usage) {
385 auto global_buffer = global_buffers_.find(key);
386 if (global_buffer == global_buffers_.end()) {
Jiwen 'Steve' Cai0057fdd2017-05-02 11:21:18 -0700387 auto ion_buffer = std::make_unique<IonBuffer>(static_cast<int>(size), 1,
388 HAL_PIXEL_FORMAT_BLOB, usage);
John Bates954796e2017-05-11 11:00:31 -0700389
390 // Some buffers are used internally. If they were configured with an
391 // invalid size or format, this will fail.
392 int result = hardware_composer_.OnNewGlobalBuffer(key, *ion_buffer.get());
393 if (result < 0)
394 return ErrorStatus(result);
Okan Arikan36d23802017-05-15 15:20:39 -0700395 global_buffer =
396 global_buffers_.insert(std::make_pair(key, std::move(ion_buffer)))
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700397 .first;
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700398 }
399
Okan Arikan36d23802017-05-15 15:20:39 -0700400 return {BorrowedNativeBufferHandle(*global_buffer->second, 0)};
Hendrik Wagenaar10e68eb2017-03-15 13:29:02 -0700401}
402
John Bates954796e2017-05-11 11:00:31 -0700403pdx::Status<void> DisplayService::DeleteGlobalBuffer(DvrGlobalBufferKey key) {
404 auto global_buffer = global_buffers_.find(key);
405 if (global_buffer != global_buffers_.end()) {
406 // Some buffers are used internally.
407 hardware_composer_.OnDeletedGlobalBuffer(key);
408 global_buffers_.erase(global_buffer);
409 }
410
411 return {0};
412}
413
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800414void DisplayService::SetDisplayConfigurationUpdateNotifier(
415 DisplayConfigurationUpdateNotifier update_notifier) {
416 update_notifier_ = update_notifier;
417}
418
419void DisplayService::NotifyDisplayConfigurationUpdate() {
420 if (update_notifier_)
421 update_notifier_();
422}
423
Corey Tabaka2251d822017-04-20 16:04:07 -0700424Status<bool> DisplayService::IsVrAppRunning(pdx::Message& /*message*/) {
Albert Chaulk356bc372017-04-05 18:01:58 -0400425 bool visible = false;
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700426 ForEachDisplaySurface(
Corey Tabaka2251d822017-04-20 16:04:07 -0700427 SurfaceType::Application,
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700428 [&visible](const std::shared_ptr<DisplaySurface>& surface) {
Corey Tabaka2251d822017-04-20 16:04:07 -0700429 if (surface->visible())
Hendrik Wagenaareaa55222017-04-06 10:56:23 -0700430 visible = true;
431 });
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400432
Corey Tabaka2251d822017-04-20 16:04:07 -0700433 return {visible};
Albert Chaulkb7c8a4b2017-03-20 13:03:39 -0400434}
435
Alex Vakulenkoa8a92782017-01-27 14:41:57 -0800436} // namespace dvr
437} // namespace android