1 /*
2 * Copyright (c) 2014 - 2016, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <core/dump_interface.h>
31 #include <core/buffer_allocator.h>
32 #include <private/color_params.h>
33 #include <utils/constants.h>
34 #include <utils/String16.h>
35 #include <cutils/properties.h>
36 #include <hardware_legacy/uevent.h>
37 #include <sys/resource.h>
38 #include <sys/prctl.h>
39 #include <binder/Parcel.h>
40 #include <QService.h>
41 #include <gr.h>
42 #include <gralloc_priv.h>
43 #include <display_config.h>
44 #include <utils/debug.h>
45 #include <sync/sync.h>
46 #include <profiler.h>
47
48 #include "hwc_buffer_allocator.h"
49 #include "hwc_buffer_sync_handler.h"
50 #include "hwc_session.h"
51 #include "hwc_debugger.h"
52 #include "hwc_display_primary.h"
53 #include "hwc_display_virtual.h"
54
55 #define __CLASS__ "HWCSession"
56
57 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
58 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
59
60 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
61
62 hwc_module_t HAL_MODULE_INFO_SYM = {
63 .common = {
64 .tag = HARDWARE_MODULE_TAG,
65 .version_major = 2,
66 .version_minor = 0,
67 .id = HWC_HARDWARE_MODULE_ID,
68 .name = "QTI Hardware Composer Module",
69 .author = "CodeAurora Forum",
70 .methods = &g_hwc_module_methods,
71 .dso = 0,
72 .reserved = {0},
73 }
74 };
75
76 namespace sdm {
77
78 Locker HWCSession::locker_;
79
Invalidate(const struct hwc_procs * procs)80 static void Invalidate(const struct hwc_procs *procs) {
81 }
82
VSync(const struct hwc_procs * procs,int disp,int64_t timestamp)83 static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
84 }
85
Hotplug(const struct hwc_procs * procs,int disp,int connected)86 static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
87 }
88
HWCSession(const hw_module_t * module)89 HWCSession::HWCSession(const hw_module_t *module) {
90 // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
91 hwc_procs_default_.invalidate = Invalidate;
92 hwc_procs_default_.vsync = VSync;
93 hwc_procs_default_.hotplug = Hotplug;
94
95 hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
96 hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
97 hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
98 hwc_composer_device_1_t::common.close = Close;
99 hwc_composer_device_1_t::prepare = Prepare;
100 hwc_composer_device_1_t::set = Set;
101 hwc_composer_device_1_t::eventControl = EventControl;
102 hwc_composer_device_1_t::setPowerMode = SetPowerMode;
103 hwc_composer_device_1_t::query = Query;
104 hwc_composer_device_1_t::registerProcs = RegisterProcs;
105 hwc_composer_device_1_t::dump = Dump;
106 hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
107 hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
108 hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
109 hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
110 hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
111 }
112
Init()113 int HWCSession::Init() {
114 int status = -EINVAL;
115 const char *qservice_name = "display.qservice";
116
117 // Start QService and connect to it.
118 qService::QService::init();
119 android::sp<qService::IQService> qservice = android::interface_cast<qService::IQService>(
120 android::defaultServiceManager()->getService(android::String16(qservice_name)));
121
122 if (qservice.get()) {
123 qservice->connect(android::sp<qClient::IQClient>(this));
124 } else {
125 DLOGE("Failed to acquire %s", qservice_name);
126 return -EINVAL;
127 }
128
129 buffer_allocator_ = new HWCBufferAllocator();
130 if (buffer_allocator_ == NULL) {
131 DLOGE("Display core initialization failed due to no memory");
132 return -ENOMEM;
133 }
134
135 buffer_sync_handler_ = new HWCBufferSyncHandler();
136 if (buffer_sync_handler_ == NULL) {
137 DLOGE("Display core initialization failed due to no memory");
138 return -ENOMEM;
139 }
140
141 DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_,
142 buffer_sync_handler_, &core_intf_);
143 if (error != kErrorNone) {
144 DLOGE("Display core initialization failed. Error = %d", error);
145 return -EINVAL;
146 }
147
148 // Create and power on primary display
149 status = HWCDisplayPrimary::Create(core_intf_, &hwc_procs_,
150 &hwc_display_[HWC_DISPLAY_PRIMARY]);
151 if (status) {
152 CoreInterface::DestroyCore();
153 return status;
154 }
155
156 color_mgr_ = HWCColorManager::CreateColorManager();
157 if (!color_mgr_) {
158 DLOGW("Failed to load HWCColorManager.");
159 }
160
161 if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
162 DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
163 HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
164 hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
165 CoreInterface::DestroyCore();
166 return -errno;
167 }
168
169 return 0;
170 }
171
Deinit()172 int HWCSession::Deinit() {
173 HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
174 hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
175 if (color_mgr_) {
176 color_mgr_->DestroyColorManager();
177 }
178 uevent_thread_exit_ = true;
179 pthread_join(uevent_thread_, NULL);
180
181 DisplayError error = CoreInterface::DestroyCore();
182 if (error != kErrorNone) {
183 DLOGE("Display core de-initialization failed. Error = %d", error);
184 }
185
186 return 0;
187 }
188
Open(const hw_module_t * module,const char * name,hw_device_t ** device)189 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
190 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
191
192 if (!module || !name || !device) {
193 DLOGE("Invalid parameters.");
194 return -EINVAL;
195 }
196
197 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
198 HWCSession *hwc_session = new HWCSession(module);
199 if (!hwc_session) {
200 return -ENOMEM;
201 }
202
203 int status = hwc_session->Init();
204 if (status != 0) {
205 delete hwc_session;
206 return status;
207 }
208
209 hwc_composer_device_1_t *composer_device = hwc_session;
210 *device = reinterpret_cast<hw_device_t *>(composer_device);
211 }
212
213 return 0;
214 }
215
Close(hw_device_t * device)216 int HWCSession::Close(hw_device_t *device) {
217 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
218
219 if (!device) {
220 return -EINVAL;
221 }
222
223 hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
224 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
225
226 hwc_session->Deinit();
227 delete hwc_session;
228
229 return 0;
230 }
231
Prepare(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)232 int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
233 hwc_display_contents_1_t **displays) {
234 DTRACE_SCOPED();
235
236 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
237 return -EINVAL;
238 }
239
240 HWCSession *hwc_session = static_cast<HWCSession *>(device);
241 hwc_procs_t const *hwc_procs = NULL;
242 bool hotplug_connect = false;
243
244 // Hold mutex only in this scope.
245 {
246 SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
247
248 hwc_procs = hwc_session->hwc_procs_;
249
250 if (hwc_session->reset_panel_) {
251 DLOGW("panel is in bad state, resetting the panel");
252 hwc_session->ResetPanel();
253 }
254
255 if (hwc_session->need_invalidate_) {
256 hwc_procs->invalidate(hwc_procs);
257 }
258
259 hwc_session->HandleSecureDisplaySession(displays);
260
261 if (hwc_session->color_mgr_) {
262 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
263 if (primary_display) {
264 int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
265 if (ret)
266 return 0;
267 }
268 }
269
270 for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
271 hwc_display_contents_1_t *content_list = displays[dpy];
272 // If external display is connected, ignore virtual display content list.
273 // If virtual display content list is valid, connect virtual display if not connected.
274 // If virtual display content list is invalid, disconnect virtual display if connected.
275 // If external display connection is pending, connect external display when virtual
276 // display is destroyed.
277 if (dpy == HWC_DISPLAY_VIRTUAL) {
278 if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL]) {
279 continue;
280 }
281
282 bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
283 bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
284
285 if (valid_content && !connected) {
286 hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
287 } else if (!valid_content && connected) {
288 hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
289
290 if (hwc_session->external_pending_connect_) {
291 DLOGI("Process pending external display connection");
292 hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
293 hwc_session->external_pending_connect_ = false;
294 hotplug_connect = true;
295 }
296 }
297 }
298
299 if (hwc_session->hwc_display_[dpy]) {
300 if (!content_list) {
301 DLOGI("Display[%d] connected. content_list is null", dpy);
302 } else if (!content_list->numHwLayers) {
303 DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
304 } else {
305 hwc_session->hwc_display_[dpy]->Prepare(content_list);
306 }
307 }
308 }
309 }
310
311 if (hotplug_connect) {
312 // notify client
313 hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
314 }
315 // Return 0, else client will go into bad state
316 return 0;
317 }
318
GetVsyncPeriod(int disp)319 int HWCSession::GetVsyncPeriod(int disp) {
320 SCOPE_LOCK(locker_);
321 // default value
322 int32_t vsync_period = 1000000000l / 60;
323 const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
324
325 if (hwc_display_[disp]) {
326 hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
327 }
328
329 return vsync_period;
330 }
331
Set(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)332 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
333 hwc_display_contents_1_t **displays) {
334 DTRACE_SCOPED();
335
336 SEQUENCE_EXIT_SCOPE_LOCK(locker_);
337
338 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
339 return -EINVAL;
340 }
341
342 HWCSession *hwc_session = static_cast<HWCSession *>(device);
343
344 if (hwc_session->color_mgr_) {
345 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
346 if (primary_display) {
347 int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
348 if (ret)
349 return 0;
350 }
351 }
352
353 for (size_t dpy = 0; dpy < num_displays; dpy++) {
354 hwc_display_contents_1_t *content_list = displays[dpy];
355
356 // Drop virtual display composition if virtual display object could not be created
357 // due to HDMI concurrency.
358 if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
359 CloseAcquireFds(content_list);
360 if (content_list) {
361 content_list->retireFenceFd = -1;
362 }
363
364 continue;
365 }
366
367 if (hwc_session->hwc_display_[dpy]) {
368 hwc_session->hwc_display_[dpy]->Commit(content_list);
369 }
370 CloseAcquireFds(content_list);
371 }
372
373 if (hwc_session->new_bw_mode_) {
374 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
375 hwc_session->new_bw_mode_ = false;
376 if (hwc_session->bw_mode_release_fd_ >= 0) {
377 close(hwc_session->bw_mode_release_fd_);
378 }
379 hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
380 }
381
382 // This is only indicative of how many times SurfaceFlinger posts
383 // frames to the display.
384 CALC_FPS();
385
386 // Return 0, else client will go into bad state
387 return 0;
388 }
389
CloseAcquireFds(hwc_display_contents_1_t * content_list)390 void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
391 if (content_list) {
392 for (size_t i = 0; i < content_list->numHwLayers; i++) {
393 int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
394 if (acquireFenceFd >= 0) {
395 close(acquireFenceFd);
396 acquireFenceFd = -1;
397 }
398 }
399
400 int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
401 if (outbufAcquireFenceFd >= 0) {
402 close(outbufAcquireFenceFd);
403 outbufAcquireFenceFd = -1;
404 }
405 }
406 }
407
EventControl(hwc_composer_device_1 * device,int disp,int event,int enable)408 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
409 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
410
411 if (!device) {
412 return -EINVAL;
413 }
414
415 HWCSession *hwc_session = static_cast<HWCSession *>(device);
416 int status = -EINVAL;
417 if (hwc_session->hwc_display_[disp]) {
418 status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
419 }
420
421 return status;
422 }
423
SetPowerMode(hwc_composer_device_1 * device,int disp,int mode)424 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
425 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
426
427 if (!device) {
428 return -EINVAL;
429 }
430
431 HWCSession *hwc_session = static_cast<HWCSession *>(device);
432 int status = -EINVAL;
433 if (hwc_session->hwc_display_[disp]) {
434 status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
435 }
436 if (disp == HWC_DISPLAY_PRIMARY && hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
437 // Set the power mode for virtual display while setting power mode for primary, as SF
438 // does not invoke SetPowerMode() for virtual display.
439 status = hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]->SetPowerMode(mode);
440 }
441
442 return status;
443 }
444
Query(hwc_composer_device_1 * device,int param,int * value)445 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
446 SCOPE_LOCK(locker_);
447
448 if (!device || !value) {
449 return -EINVAL;
450 }
451
452 int status = 0;
453
454 switch (param) {
455 case HWC_BACKGROUND_LAYER_SUPPORTED:
456 value[0] = 1;
457 break;
458
459 default:
460 status = -EINVAL;
461 }
462
463 return status;
464 }
465
RegisterProcs(hwc_composer_device_1 * device,hwc_procs_t const * procs)466 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
467 SCOPE_LOCK(locker_);
468
469 if (!device || !procs) {
470 return;
471 }
472
473 HWCSession *hwc_session = static_cast<HWCSession *>(device);
474 hwc_session->hwc_procs_ = procs;
475 }
476
Dump(hwc_composer_device_1 * device,char * buffer,int length)477 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
478 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
479
480 if (!device || !buffer || !length) {
481 return;
482 }
483
484 DumpInterface::GetDump(buffer, UINT32(length));
485 }
486
GetDisplayConfigs(hwc_composer_device_1 * device,int disp,uint32_t * configs,size_t * num_configs)487 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
488 size_t *num_configs) {
489 SCOPE_LOCK(locker_);
490
491 if (!device || !configs || !num_configs) {
492 return -EINVAL;
493 }
494
495 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
496 return -EINVAL;
497 }
498
499 HWCSession *hwc_session = static_cast<HWCSession *>(device);
500 int status = -EINVAL;
501 if (hwc_session->hwc_display_[disp]) {
502 status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
503 }
504
505 return status;
506 }
507
GetDisplayAttributes(hwc_composer_device_1 * device,int disp,uint32_t config,const uint32_t * attributes,int32_t * values)508 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
509 const uint32_t *attributes, int32_t *values) {
510 SCOPE_LOCK(locker_);
511
512 if (!device || !attributes || !values) {
513 return -EINVAL;
514 }
515
516 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
517 return -EINVAL;
518 }
519
520 HWCSession *hwc_session = static_cast<HWCSession *>(device);
521 int status = -EINVAL;
522 if (hwc_session->hwc_display_[disp]) {
523 status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, attributes, values);
524 }
525
526 return status;
527 }
528
GetActiveConfig(hwc_composer_device_1 * device,int disp)529 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
530 SCOPE_LOCK(locker_);
531
532 if (!device) {
533 return -EINVAL;
534 }
535
536 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
537 return -EINVAL;
538 }
539
540 HWCSession *hwc_session = static_cast<HWCSession *>(device);
541 int active_config = -1;
542 if (hwc_session->hwc_display_[disp]) {
543 active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
544 }
545
546 return active_config;
547 }
548
SetActiveConfig(hwc_composer_device_1 * device,int disp,int index)549 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
550 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
551
552 if (!device) {
553 return -EINVAL;
554 }
555
556 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
557 return -EINVAL;
558 }
559
560 HWCSession *hwc_session = static_cast<HWCSession *>(device);
561 int status = -EINVAL;
562
563 if (hwc_session->hwc_display_[disp]) {
564 status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
565 }
566
567 return status;
568 }
569
SetCursorPositionAsync(hwc_composer_device_1 * device,int disp,int x,int y)570 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
571 DTRACE_SCOPED();
572
573 SCOPE_LOCK(locker_);
574
575 if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
576 return -EINVAL;
577 }
578
579 int status = -EINVAL;
580 HWCSession *hwc_session = static_cast<HWCSession *>(device);
581 if (hwc_session->hwc_display_[disp]) {
582 status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
583 }
584
585 return status;
586 }
587
ConnectDisplay(int disp,hwc_display_contents_1_t * content_list)588 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
589 DLOGI("Display = %d", disp);
590
591 int status = 0;
592 uint32_t primary_width = 0;
593 uint32_t primary_height = 0;
594
595 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
596
597 if (disp == HWC_DISPLAY_EXTERNAL) {
598 status = HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
599 &hwc_display_[disp]);
600 } else if (disp == HWC_DISPLAY_VIRTUAL) {
601 status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
602 content_list, &hwc_display_[disp]);
603 } else {
604 DLOGE("Invalid display type");
605 return -1;
606 }
607
608 if (!status) {
609 hwc_display_[disp]->SetSecureDisplay(secure_display_active_);
610 }
611
612 return status;
613 }
614
DisconnectDisplay(int disp)615 int HWCSession::DisconnectDisplay(int disp) {
616 DLOGI("Display = %d", disp);
617
618 if (disp == HWC_DISPLAY_EXTERNAL) {
619 HWCDisplayExternal::Destroy(hwc_display_[disp]);
620 } else if (disp == HWC_DISPLAY_VIRTUAL) {
621 HWCDisplayVirtual::Destroy(hwc_display_[disp]);
622 } else {
623 DLOGE("Invalid display type");
624 return -1;
625 }
626
627 hwc_display_[disp] = NULL;
628
629 return 0;
630 }
631
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)632 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
633 android::Parcel *output_parcel) {
634 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
635
636 android::status_t status = 0;
637
638 switch (command) {
639 case qService::IQService::DYNAMIC_DEBUG:
640 DynamicDebug(input_parcel);
641 break;
642
643 case qService::IQService::SCREEN_REFRESH:
644 hwc_procs_->invalidate(hwc_procs_);
645 break;
646
647 case qService::IQService::SET_IDLE_TIMEOUT:
648 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
649 uint32_t timeout = UINT32(input_parcel->readInt32());
650 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
651 }
652 break;
653
654 case qService::IQService::SET_FRAME_DUMP_CONFIG:
655 SetFrameDumpConfig(input_parcel);
656 break;
657
658 case qService::IQService::SET_MAX_PIPES_PER_MIXER:
659 status = SetMaxMixerStages(input_parcel);
660 break;
661
662 case qService::IQService::SET_DISPLAY_MODE:
663 status = SetDisplayMode(input_parcel);
664 break;
665
666 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
667 status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
668 break;
669
670 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
671 status = ConfigureRefreshRate(input_parcel);
672 break;
673
674 case qService::IQService::SET_VIEW_FRAME:
675 break;
676
677 case qService::IQService::TOGGLE_SCREEN_UPDATES:
678 status = ToggleScreenUpdates(input_parcel, output_parcel);
679 break;
680
681 case qService::IQService::QDCM_SVC_CMDS:
682 status = QdcmCMDHandler(input_parcel, output_parcel);
683 break;
684
685 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
686 status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
687 break;
688
689 case qService::IQService::CONTROL_PARTIAL_UPDATE:
690 status = ControlPartialUpdate(input_parcel, output_parcel);
691 break;
692
693 case qService::IQService::SET_ACTIVE_CONFIG:
694 status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
695 break;
696
697 case qService::IQService::GET_ACTIVE_CONFIG:
698 status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
699 break;
700
701 case qService::IQService::GET_CONFIG_COUNT:
702 status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
703 break;
704
705 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
706 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
707 break;
708
709 case qService::IQService::GET_PANEL_BRIGHTNESS:
710 status = GetPanelBrightness(input_parcel, output_parcel);
711 break;
712
713 case qService::IQService::SET_PANEL_BRIGHTNESS:
714 status = SetPanelBrightness(input_parcel, output_parcel);
715 break;
716
717 case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
718 status = GetVisibleDisplayRect(input_parcel, output_parcel);
719 break;
720
721 case qService::IQService::SET_CAMERA_STATUS:
722 status = SetDynamicBWForCamera(input_parcel, output_parcel);
723 break;
724
725 case qService::IQService::GET_BW_TRANSACTION_STATUS:
726 status = GetBWTransactionStatus(input_parcel, output_parcel);
727 break;
728
729 default:
730 DLOGW("QService command = %d is not supported", command);
731 return -EINVAL;
732 }
733
734 return status;
735 }
736
ToggleScreenUpdates(const android::Parcel * input_parcel,android::Parcel * output_parcel)737 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
738 android::Parcel *output_parcel) {
739 int input = input_parcel->readInt32();
740 int error = android::BAD_VALUE;
741
742 if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
743 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
744 if (error != 0) {
745 DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
746 }
747 }
748 output_parcel->writeInt32(error);
749
750 return error;
751 }
752
SetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)753 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
754 android::Parcel *output_parcel) {
755 int level = input_parcel->readInt32();
756 int error = android::BAD_VALUE;
757
758 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
759 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
760 if (error != 0) {
761 DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
762 }
763 }
764 output_parcel->writeInt32(error);
765
766 return error;
767 }
768
GetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)769 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
770 android::Parcel *output_parcel) {
771 int error = android::BAD_VALUE;
772 int ret = error;
773
774 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
775 error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
776 if (error != 0) {
777 ret = error;
778 DLOGE("Failed to get the panel brightness. Error = %d", error);
779 }
780 }
781 output_parcel->writeInt32(ret);
782
783 return error;
784 }
785
ControlPartialUpdate(const android::Parcel * input_parcel,android::Parcel * out)786 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
787 android::Parcel *out) {
788 DisplayError error = kErrorNone;
789 int ret = 0;
790 uint32_t disp_id = UINT32(input_parcel->readInt32());
791 uint32_t enable = UINT32(input_parcel->readInt32());
792
793 if (disp_id != HWC_DISPLAY_PRIMARY) {
794 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
795 ret = -EINVAL;
796 out->writeInt32(ret);
797 return ret;
798 }
799
800 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
801 DLOGE("primary display object is not instantiated");
802 ret = -EINVAL;
803 out->writeInt32(ret);
804 return ret;
805 }
806
807 uint32_t pending = 0;
808 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
809
810 if (error == kErrorNone) {
811 if (!pending) {
812 out->writeInt32(ret);
813 return ret;
814 }
815 } else if (error == kErrorNotSupported) {
816 out->writeInt32(ret);
817 return ret;
818 } else {
819 ret = -EINVAL;
820 out->writeInt32(ret);
821 return ret;
822 }
823
824 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
825 hwc_procs_->invalidate(hwc_procs_);
826
827 // Wait until partial update control is complete
828 ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
829
830 out->writeInt32(ret);
831
832 return ret;
833 }
834
HandleSetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)835 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
836 android::Parcel *output_parcel) {
837 int config = input_parcel->readInt32();
838 int dpy = input_parcel->readInt32();
839 int error = android::BAD_VALUE;
840
841 if (dpy > HWC_DISPLAY_VIRTUAL) {
842 return android::BAD_VALUE;
843 }
844
845 if (hwc_display_[dpy]) {
846 error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
847 if (error == 0) {
848 hwc_procs_->invalidate(hwc_procs_);
849 }
850 }
851
852 return error;
853 }
854
HandleGetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)855 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
856 android::Parcel *output_parcel) {
857 int dpy = input_parcel->readInt32();
858 int error = android::BAD_VALUE;
859
860 if (dpy > HWC_DISPLAY_VIRTUAL) {
861 return android::BAD_VALUE;
862 }
863
864 if (hwc_display_[dpy]) {
865 uint32_t config = 0;
866 error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
867 if (error == 0) {
868 output_parcel->writeInt32(INT(config));
869 }
870 }
871
872 return error;
873 }
874
HandleGetDisplayConfigCount(const android::Parcel * input_parcel,android::Parcel * output_parcel)875 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
876 android::Parcel *output_parcel) {
877 int dpy = input_parcel->readInt32();
878 int error = android::BAD_VALUE;
879
880 if (dpy > HWC_DISPLAY_VIRTUAL) {
881 return android::BAD_VALUE;
882 }
883
884 uint32_t count = 0;
885 if (hwc_display_[dpy]) {
886 error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
887 if (error == 0) {
888 output_parcel->writeInt32(INT(count));
889 }
890 }
891
892 return error;
893 }
894
HandleGetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)895 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
896 *input_parcel,
897 android::Parcel *output_parcel) {
898 int config = input_parcel->readInt32();
899 int dpy = input_parcel->readInt32();
900 int error = android::BAD_VALUE;
901 DisplayConfigVariableInfo attributes;
902
903 if (dpy > HWC_DISPLAY_VIRTUAL) {
904 return android::BAD_VALUE;
905 }
906
907 if (hwc_display_[dpy]) {
908 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &attributes);
909 if (error == 0) {
910 output_parcel->writeInt32(INT(attributes.vsync_period_ns));
911 output_parcel->writeInt32(INT(attributes.x_pixels));
912 output_parcel->writeInt32(INT(attributes.y_pixels));
913 output_parcel->writeFloat(attributes.x_dpi);
914 output_parcel->writeFloat(attributes.y_dpi);
915 output_parcel->writeInt32(0); // Panel type, unsupported.
916 }
917 }
918
919 return error;
920 }
921
SetSecondaryDisplayStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)922 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
923 android::Parcel *output_parcel) {
924 int ret = -EINVAL;
925
926 uint32_t display_id = UINT32(input_parcel->readInt32());
927 uint32_t display_status = UINT32(input_parcel->readInt32());
928
929 DLOGI("Display = %d, Status = %d", display_id, display_status);
930
931 if (display_id >= HWC_NUM_DISPLAY_TYPES) {
932 DLOGE("Invalid display_id");
933 } else if (display_id == HWC_DISPLAY_PRIMARY) {
934 DLOGE("Not supported for this display");
935 } else if (!hwc_display_[display_id]) {
936 DLOGW("Display is not connected");
937 } else {
938 ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
939 }
940
941 output_parcel->writeInt32(ret);
942
943 return ret;
944 }
945
ConfigureRefreshRate(const android::Parcel * input_parcel)946 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
947 uint32_t operation = UINT32(input_parcel->readInt32());
948 switch (operation) {
949 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
950 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
951 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
952 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
953 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
954 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
955 case qdutils::SET_BINDER_DYN_REFRESH_RATE:
956 {
957 uint32_t refresh_rate = UINT32(input_parcel->readInt32());
958 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
959 HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
960 refresh_rate);
961 }
962 default:
963 DLOGW("Invalid operation %d", operation);
964 return -EINVAL;
965 }
966
967 return 0;
968 }
969
SetDisplayMode(const android::Parcel * input_parcel)970 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
971 uint32_t mode = UINT32(input_parcel->readInt32());
972 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
973 }
974
SetMaxMixerStages(const android::Parcel * input_parcel)975 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
976 DisplayError error = kErrorNone;
977 uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
978 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
979
980 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
981 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
982 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
983 if (error != kErrorNone) {
984 return -EINVAL;
985 }
986 }
987 }
988
989 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
990 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
991 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
992 if (error != kErrorNone) {
993 return -EINVAL;
994 }
995 }
996 }
997
998 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
999 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1000 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1001 if (error != kErrorNone) {
1002 return -EINVAL;
1003 }
1004 }
1005 }
1006
1007 return 0;
1008 }
1009
SetDynamicBWForCamera(const android::Parcel * input_parcel,android::Parcel * output_parcel)1010 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
1011 android::Parcel *output_parcel) {
1012 DisplayError error = kErrorNone;
1013 uint32_t camera_status = UINT32(input_parcel->readInt32());
1014 HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
1015
1016 // trigger invalidate to apply new bw caps.
1017 hwc_procs_->invalidate(hwc_procs_);
1018
1019 error = core_intf_->SetMaxBandwidthMode(mode);
1020 if (error != kErrorNone) {
1021 return -EINVAL;
1022 }
1023
1024 new_bw_mode_ = true;
1025 need_invalidate_ = true;
1026
1027 return 0;
1028 }
1029
GetBWTransactionStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1030 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
1031 android::Parcel *output_parcel) {
1032 bool state = true;
1033
1034 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1035 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
1036 DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
1037 state = false;
1038 }
1039 output_parcel->writeInt32(state);
1040 }
1041
1042 return 0;
1043 }
1044
SetFrameDumpConfig(const android::Parcel * input_parcel)1045 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1046 uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1047 uint32_t bit_mask_display_type = UINT32(input_parcel->readInt32());
1048 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1049
1050 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_PRIMARY)) {
1051 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1052 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1053 }
1054 }
1055
1056 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_EXTERNAL)) {
1057 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1058 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1059 }
1060 }
1061
1062 if (IS_BIT_SET(bit_mask_display_type, HWC_DISPLAY_VIRTUAL)) {
1063 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1064 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1065 }
1066 }
1067 }
1068
DynamicDebug(const android::Parcel * input_parcel)1069 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1070 int type = input_parcel->readInt32();
1071 bool enable = (input_parcel->readInt32() > 0);
1072 DLOGI("type = %d enable = %d", type, enable);
1073 int verbose_level = input_parcel->readInt32();
1074
1075 switch (type) {
1076 case qService::IQService::DEBUG_ALL:
1077 HWCDebugHandler::DebugAll(enable, verbose_level);
1078 break;
1079
1080 case qService::IQService::DEBUG_MDPCOMP:
1081 HWCDebugHandler::DebugStrategy(enable, verbose_level);
1082 HWCDebugHandler::DebugCompManager(enable, verbose_level);
1083 break;
1084
1085 case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1086 HWCDebugHandler::DebugResources(enable, verbose_level);
1087 break;
1088
1089 case qService::IQService::DEBUG_DRIVER_CONFIG:
1090 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1091 break;
1092
1093 case qService::IQService::DEBUG_ROTATOR:
1094 HWCDebugHandler::DebugResources(enable, verbose_level);
1095 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1096 HWCDebugHandler::DebugRotator(enable, verbose_level);
1097 break;
1098
1099 case qService::IQService::DEBUG_QDCM:
1100 HWCDebugHandler::DebugQdcm(enable, verbose_level);
1101 break;
1102
1103 default:
1104 DLOGW("type = %d is not supported", type);
1105 }
1106 }
1107
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)1108 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1109 android::Parcel *output_parcel) {
1110 int ret = 0;
1111 int32_t *brightness_value = NULL;
1112 uint32_t display_id(0);
1113 PPPendingParams pending_action;
1114 PPDisplayAPIPayload resp_payload, req_payload;
1115
1116 if (!color_mgr_) {
1117 return -1;
1118 }
1119
1120 pending_action.action = kNoAction;
1121 pending_action.params = NULL;
1122
1123 // Read display_id, payload_size and payload from in_parcel.
1124 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1125 if (!ret) {
1126 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1127 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
1128 &resp_payload, &pending_action);
1129
1130 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1131 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1132 &pending_action);
1133 }
1134
1135 if (ret) {
1136 output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
1137 req_payload.DestroyPayload();
1138 resp_payload.DestroyPayload();
1139 return ret;
1140 }
1141
1142 switch (pending_action.action) {
1143 case kInvalidating:
1144 hwc_procs_->invalidate(hwc_procs_);
1145 break;
1146 case kEnterQDCMMode:
1147 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1148 break;
1149 case kExitQDCMMode:
1150 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1151 break;
1152 case kApplySolidFill:
1153 ret = color_mgr_->SetSolidFill(pending_action.params,
1154 true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1155 hwc_procs_->invalidate(hwc_procs_);
1156 break;
1157 case kDisableSolidFill:
1158 ret = color_mgr_->SetSolidFill(pending_action.params,
1159 false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1160 hwc_procs_->invalidate(hwc_procs_);
1161 break;
1162 case kSetPanelBrightness:
1163 brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1164 if (brightness_value == NULL) {
1165 DLOGE("Brightness value is Null");
1166 return -EINVAL;
1167 }
1168 if (HWC_DISPLAY_PRIMARY == display_id)
1169 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1170 break;
1171 case kNoAction:
1172 break;
1173 default:
1174 DLOGW("Invalid pending action = %d!", pending_action.action);
1175 break;
1176 }
1177
1178 // for display API getter case, marshall returned params into out_parcel.
1179 output_parcel->writeInt32(ret);
1180 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1181 req_payload.DestroyPayload();
1182 resp_payload.DestroyPayload();
1183
1184 return (ret? -EINVAL : 0);
1185 }
1186
OnMinHdcpEncryptionLevelChange(const android::Parcel * input_parcel,android::Parcel * output_parcel)1187 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
1188 android::Parcel *output_parcel) {
1189 int ret = -EINVAL;
1190 uint32_t display_id = UINT32(input_parcel->readInt32());
1191 uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1192
1193 DLOGI("Display %d", display_id);
1194
1195 if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1196 DLOGE("Invalid display_id");
1197 } else if (display_id != HWC_DISPLAY_EXTERNAL) {
1198 DLOGE("Not supported for display");
1199 } else if (!hwc_display_[display_id]) {
1200 DLOGW("Display is not connected");
1201 } else {
1202 ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
1203 }
1204
1205 output_parcel->writeInt32(ret);
1206
1207 return ret;
1208 }
1209
HWCUeventThread(void * context)1210 void* HWCSession::HWCUeventThread(void *context) {
1211 if (context) {
1212 return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
1213 }
1214
1215 return NULL;
1216 }
1217
HWCUeventThreadHandler()1218 void* HWCSession::HWCUeventThreadHandler() {
1219 static char uevent_data[PAGE_SIZE];
1220 int length = 0;
1221 prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
1222 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1223 if (!uevent_init()) {
1224 DLOGE("Failed to init uevent");
1225 pthread_exit(0);
1226 return NULL;
1227 }
1228
1229 while (!uevent_thread_exit_) {
1230 // keep last 2 zeroes to ensure double 0 termination
1231 length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
1232
1233 if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
1234 DLOGI("Uevent HDMI = %s", uevent_data);
1235 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1236 if (connected >= 0) {
1237 DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1238 if (HotPlugHandler(connected) == -1) {
1239 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1240 }
1241 }
1242 } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
1243 DLOGI("Uevent FB0 = %s", uevent_data);
1244 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1245 if (panel_reset == 0) {
1246 if (hwc_procs_) {
1247 reset_panel_ = true;
1248 hwc_procs_->invalidate(hwc_procs_);
1249 } else {
1250 DLOGW("Ignore resetpanel - hwc_proc not registered");
1251 }
1252 }
1253 }
1254 }
1255 pthread_exit(0);
1256
1257 return NULL;
1258 }
1259
GetEventValue(const char * uevent_data,int length,const char * event_info)1260 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1261 const char *iterator_str = uevent_data;
1262 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1263 char *pstr = strstr(iterator_str, event_info);
1264 if (pstr != NULL) {
1265 return (atoi(iterator_str + strlen(event_info)));
1266 }
1267 iterator_str += strlen(iterator_str) + 1;
1268 }
1269
1270 return -1;
1271 }
1272
ResetPanel()1273 void HWCSession::ResetPanel() {
1274 int status = -EINVAL;
1275
1276 DLOGI("Powering off primary");
1277 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
1278 if (status) {
1279 DLOGE("power-off on primary failed with error = %d", status);
1280 }
1281
1282 DLOGI("Restoring power mode on primary");
1283 int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
1284 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1285 if (status) {
1286 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1287 }
1288
1289 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
1290 if (status) {
1291 DLOGE("enabling vsync failed for primary with error = %d", status);
1292 }
1293
1294 reset_panel_ = false;
1295 }
1296
HotPlugHandler(bool connected)1297 int HWCSession::HotPlugHandler(bool connected) {
1298 int status = 0;
1299 bool notify_hotplug = false;
1300
1301 // To prevent sending events to client while a lock is held, acquire scope locks only within
1302 // below scope so that those get automatically unlocked after the scope ends.
1303 {
1304 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
1305
1306 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1307 DLOGE("Primay display is not connected.");
1308 return -1;
1309 }
1310
1311 if (connected) {
1312 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1313 DLOGE("HDMI is already connected");
1314 return -1;
1315 }
1316
1317 // Connect external display if virtual display is not connected.
1318 // Else, defer external display connection and process it when virtual display
1319 // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1320 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1321 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
1322 if (status) {
1323 return status;
1324 }
1325 notify_hotplug = true;
1326 } else {
1327 DLOGI("Virtual display is connected, pending connection");
1328 external_pending_connect_ = true;
1329 }
1330 } else {
1331 // Do not return error if external display is not in connected status.
1332 // Due to virtual display concurrency, external display connection might be still pending
1333 // but hdmi got disconnected before pending connection could be processed.
1334 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1335 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1336 notify_hotplug = true;
1337 }
1338 external_pending_connect_ = false;
1339 }
1340 }
1341 if (connected && notify_hotplug) {
1342 // trigger screen refresh to ensure sufficient resources are available to process new
1343 // new display connection.
1344 hwc_procs_->invalidate(hwc_procs_);
1345 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1346 usleep(vsync_period * 2 / 1000);
1347 }
1348 // notify client
1349 if (notify_hotplug) {
1350 hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
1351 }
1352
1353 return 0;
1354 }
1355
HandleSecureDisplaySession(hwc_display_contents_1_t ** displays)1356 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
1357 secure_display_active_ = false;
1358 if (!*displays) {
1359 DLOGW("Invalid display contents");
1360 return;
1361 }
1362
1363 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
1364 if (!content_list) {
1365 DLOGW("Invalid primary content list");
1366 return;
1367 }
1368 size_t num_hw_layers = content_list->numHwLayers;
1369
1370 for (size_t i = 0; i < num_hw_layers - 1; i++) {
1371 hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
1372 const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
1373 if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
1374 secure_display_active_ = true;
1375 }
1376 }
1377
1378 for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
1379 if (hwc_display_[dpy]) {
1380 hwc_display_[dpy]->SetSecureDisplay(secure_display_active_);
1381 }
1382 }
1383 }
1384
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)1385 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1386 android::Parcel *output_parcel) {
1387 int dpy = input_parcel->readInt32();
1388
1389 if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
1390 return android::BAD_VALUE;;
1391 }
1392
1393 if (!hwc_display_[dpy]) {
1394 return android::NO_INIT;
1395 }
1396
1397 hwc_rect_t visible_rect = {0, 0, 0, 0};
1398 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1399 if (error < 0) {
1400 return error;
1401 }
1402
1403 output_parcel->writeInt32(visible_rect.left);
1404 output_parcel->writeInt32(visible_rect.top);
1405 output_parcel->writeInt32(visible_rect.right);
1406 output_parcel->writeInt32(visible_rect.bottom);
1407
1408 return android::NO_ERROR;
1409 }
1410
1411 } // namespace sdm
1412
1413