1 /*
2 * Copyright (c) 2014 - 2017, 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 #include <bitset>
48 #include <vector>
49
50 #include "hwc_buffer_allocator.h"
51 #include "hwc_buffer_sync_handler.h"
52 #include "hwc_session.h"
53 #include "hwc_debugger.h"
54 #include "hwc_display_null.h"
55 #include "hwc_display_primary.h"
56 #include "hwc_display_virtual.h"
57 #include "hwc_display_external_test.h"
58 #include "qd_utils.h"
59
60 #define __CLASS__ "HWCSession"
61
62 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
63 #define HWC_UEVENT_GRAPHICS_FB0 "change@/devices/virtual/graphics/fb0"
64
65 static sdm::HWCSession::HWCModuleMethods g_hwc_module_methods;
66
67 hwc_module_t HAL_MODULE_INFO_SYM = {
68 .common = {
69 .tag = HARDWARE_MODULE_TAG,
70 .version_major = 2,
71 .version_minor = 0,
72 .id = HWC_HARDWARE_MODULE_ID,
73 .name = "QTI Hardware Composer Module",
74 .author = "CodeAurora Forum",
75 .methods = &g_hwc_module_methods,
76 .dso = 0,
77 .reserved = {0},
78 }
79 };
80
81 namespace sdm {
82
83 Locker HWCSession::locker_;
84
Invalidate(const struct hwc_procs * procs)85 static void Invalidate(const struct hwc_procs *procs) {
86 }
87
VSync(const struct hwc_procs * procs,int disp,int64_t timestamp)88 static void VSync(const struct hwc_procs* procs, int disp, int64_t timestamp) {
89 }
90
Hotplug(const struct hwc_procs * procs,int disp,int connected)91 static void Hotplug(const struct hwc_procs* procs, int disp, int connected) {
92 }
93
HWCSession(const hw_module_t * module)94 HWCSession::HWCSession(const hw_module_t *module) {
95 // By default, drop any events. Calls will be routed to SurfaceFlinger after registerProcs.
96 hwc_procs_default_.invalidate = Invalidate;
97 hwc_procs_default_.vsync = VSync;
98 hwc_procs_default_.hotplug = Hotplug;
99
100 hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
101 hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_5;
102 hwc_composer_device_1_t::common.module = const_cast<hw_module_t*>(module);
103 hwc_composer_device_1_t::common.close = Close;
104 hwc_composer_device_1_t::prepare = Prepare;
105 hwc_composer_device_1_t::set = Set;
106 hwc_composer_device_1_t::eventControl = EventControl;
107 hwc_composer_device_1_t::setPowerMode = SetPowerMode;
108 hwc_composer_device_1_t::query = Query;
109 hwc_composer_device_1_t::registerProcs = RegisterProcs;
110 hwc_composer_device_1_t::dump = Dump;
111 hwc_composer_device_1_t::getDisplayConfigs = GetDisplayConfigs;
112 hwc_composer_device_1_t::getDisplayAttributes = GetDisplayAttributes;
113 hwc_composer_device_1_t::getActiveConfig = GetActiveConfig;
114 hwc_composer_device_1_t::setActiveConfig = SetActiveConfig;
115 hwc_composer_device_1_t::setCursorPositionAsync = SetCursorPositionAsync;
116 }
117
Init()118 int HWCSession::Init() {
119 int status = -EINVAL;
120 const char *qservice_name = "display.qservice";
121
122 // Start QService and connect to it.
123 qService::QService::init();
124 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
125 android::defaultServiceManager()->getService(android::String16(qservice_name)));
126
127 if (iqservice.get()) {
128 iqservice->connect(android::sp<qClient::IQClient>(this));
129 qservice_ = reinterpret_cast<qService::QService* >(iqservice.get());
130 } else {
131 DLOGE("Failed to acquire %s", qservice_name);
132 return -EINVAL;
133 }
134
135 DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), &buffer_allocator_,
136 &buffer_sync_handler_, &socket_handler_,
137 &core_intf_);
138 if (error != kErrorNone) {
139 DLOGE("Display core initialization failed. Error = %d", error);
140 return -EINVAL;
141 }
142
143 // Read which display is first, and create it and store it in primary slot
144 HWDisplayInterfaceInfo hw_disp_info;
145 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
146 if (error == kErrorNone) {
147 if (hw_disp_info.type == kHDMI) {
148 // HDMI is primary display. If already connected, then create it and store in
149 // primary display slot. If not connected, create a NULL display for now.
150 HWCDebugHandler::Get()->SetProperty("persist.sys.is_hdmi_primary", "1");
151 is_hdmi_primary_ = true;
152 if (hw_disp_info.is_connected) {
153 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, 0, 0, false);
154 is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
155 } else {
156 // NullDisplay simply closes all its fences, and advertizes a standard
157 // resolution to SurfaceFlinger
158 status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
159 &hwc_display_[HWC_DISPLAY_PRIMARY]);
160 }
161 } else {
162 // Create and power on primary display
163 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
164 &hwc_display_[HWC_DISPLAY_PRIMARY]);
165 }
166 } else {
167 // Create and power on primary display
168 status = HWCDisplayPrimary::Create(core_intf_, &buffer_allocator_, &hwc_procs_, qservice_,
169 &hwc_display_[HWC_DISPLAY_PRIMARY]);
170 }
171
172 if (status) {
173 CoreInterface::DestroyCore();
174 return status;
175 }
176
177 color_mgr_ = HWCColorManager::CreateColorManager();
178 if (!color_mgr_) {
179 DLOGW("Failed to load HWCColorManager.");
180 }
181
182 if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {
183 DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));
184 HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
185 hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
186 CoreInterface::DestroyCore();
187 return -errno;
188 }
189
190 connected_displays_[HWC_DISPLAY_PRIMARY] = 1;
191 return 0;
192 }
193
Deinit()194 int HWCSession::Deinit() {
195 HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);
196 hwc_display_[HWC_DISPLAY_PRIMARY] = 0;
197 if (color_mgr_) {
198 color_mgr_->DestroyColorManager();
199 }
200 uevent_thread_exit_ = true;
201 pthread_join(uevent_thread_, NULL);
202
203 DisplayError error = CoreInterface::DestroyCore();
204 if (error != kErrorNone) {
205 DLOGE("Display core de-initialization failed. Error = %d", error);
206 }
207
208 connected_displays_[HWC_DISPLAY_PRIMARY] = 0;
209 return 0;
210 }
211
Open(const hw_module_t * module,const char * name,hw_device_t ** device)212 int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {
213 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
214
215 if (!module || !name || !device) {
216 DLOGE("Invalid parameters.");
217 return -EINVAL;
218 }
219
220 if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {
221 HWCSession *hwc_session = new HWCSession(module);
222 if (!hwc_session) {
223 return -ENOMEM;
224 }
225
226 int status = hwc_session->Init();
227 if (status != 0) {
228 delete hwc_session;
229 return status;
230 }
231
232 hwc_composer_device_1_t *composer_device = hwc_session;
233 *device = reinterpret_cast<hw_device_t *>(composer_device);
234 }
235
236 return 0;
237 }
238
Close(hw_device_t * device)239 int HWCSession::Close(hw_device_t *device) {
240 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
241
242 if (!device) {
243 return -EINVAL;
244 }
245
246 hwc_composer_device_1_t *composer_device = reinterpret_cast<hwc_composer_device_1_t *>(device);
247 HWCSession *hwc_session = static_cast<HWCSession *>(composer_device);
248
249 hwc_session->Deinit();
250 delete hwc_session;
251
252 return 0;
253 }
254
Prepare(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)255 int HWCSession::Prepare(hwc_composer_device_1 *device, size_t num_displays,
256 hwc_display_contents_1_t **displays) {
257 DTRACE_SCOPED();
258
259 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
260 return -EINVAL;
261 }
262
263 HWCSession *hwc_session = static_cast<HWCSession *>(device);
264 hwc_procs_t const *hwc_procs = NULL;
265 bool hotplug_connect = false;
266
267 // Hold mutex only in this scope.
268 {
269 SEQUENCE_ENTRY_SCOPE_LOCK(locker_);
270
271 hwc_procs = hwc_session->hwc_procs_;
272
273 if (hwc_session->reset_panel_) {
274 DLOGW("panel is in bad state, resetting the panel");
275 hwc_session->ResetPanel();
276 }
277
278 if (hwc_session->need_invalidate_) {
279 hwc_procs->invalidate(hwc_procs);
280 hwc_session->need_invalidate_ = false;
281 }
282
283 hwc_session->HandleSecureDisplaySession(displays);
284
285 if (hwc_session->color_mgr_) {
286 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
287 if (primary_display && !hwc_session->is_hdmi_primary_) {
288 int ret = hwc_session->color_mgr_->SolidFillLayersPrepare(displays, primary_display);
289 if (ret)
290 return 0;
291 }
292 }
293
294 for (ssize_t dpy = static_cast<ssize_t>(num_displays - 1); dpy >= 0; dpy--) {
295 hwc_display_contents_1_t *content_list = displays[dpy];
296 // If external display is connected, ignore virtual display content list.
297 // If virtual display content list is valid, connect virtual display if not connected.
298 // If virtual display content list is invalid, disconnect virtual display if connected.
299 // If external display connection is pending, connect external display when virtual
300 // display is destroyed.
301 // If HDMI is primary and the output format is YUV then ignore the virtual display
302 // content list.
303 if (dpy == HWC_DISPLAY_VIRTUAL) {
304 if (hwc_session->hwc_display_[HWC_DISPLAY_EXTERNAL] ||
305 (hwc_session->is_hdmi_primary_ && hwc_session->is_hdmi_yuv_)) {
306 continue;
307 }
308
309 bool valid_content = HWCDisplayVirtual::IsValidContentList(content_list);
310 bool connected = (hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL] != NULL);
311
312 if (valid_content && !connected) {
313 hwc_session->ConnectDisplay(HWC_DISPLAY_VIRTUAL, content_list);
314 } else if (!valid_content && connected) {
315 hwc_session->DisconnectDisplay(HWC_DISPLAY_VIRTUAL);
316
317 if (hwc_session->external_pending_connect_) {
318 DLOGI("Process pending external display connection");
319 hwc_session->ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
320 hwc_session->external_pending_connect_ = false;
321 hotplug_connect = true;
322 }
323 }
324 }
325
326 if (hwc_session->hwc_display_[dpy]) {
327 if (!content_list) {
328 DLOGI("Display[%d] connected. content_list is null", dpy);
329 } else if (!content_list->numHwLayers) {
330 DLOGE("Display[%d] connected. numHwLayers is zero", dpy);
331 } else {
332 hwc_session->hwc_display_[dpy]->Prepare(content_list);
333 }
334 }
335 }
336 }
337
338 if (hotplug_connect) {
339 // notify client
340 hwc_procs->hotplug(hwc_procs, HWC_DISPLAY_EXTERNAL, true);
341 }
342 // Return 0, else client will go into bad state
343 return 0;
344 }
345
GetVsyncPeriod(int disp)346 int HWCSession::GetVsyncPeriod(int disp) {
347 SCOPE_LOCK(locker_);
348 // default value
349 int32_t vsync_period = 1000000000l / 60;
350 const uint32_t attribute = HWC_DISPLAY_VSYNC_PERIOD;
351
352 if (hwc_display_[disp]) {
353 hwc_display_[disp]->GetDisplayAttributes(0, &attribute, &vsync_period);
354 }
355
356 return vsync_period;
357 }
358
Set(hwc_composer_device_1 * device,size_t num_displays,hwc_display_contents_1_t ** displays)359 int HWCSession::Set(hwc_composer_device_1 *device, size_t num_displays,
360 hwc_display_contents_1_t **displays) {
361 DTRACE_SCOPED();
362
363 SEQUENCE_EXIT_SCOPE_LOCK(locker_);
364
365 if (!device || !displays || num_displays > HWC_NUM_DISPLAY_TYPES) {
366 return -EINVAL;
367 }
368
369 HWCSession *hwc_session = static_cast<HWCSession *>(device);
370
371 if (hwc_session->color_mgr_) {
372 HWCDisplay *primary_display = hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY];
373 if (primary_display) {
374 int ret = hwc_session->color_mgr_->SolidFillLayersSet(displays, primary_display);
375 if (ret)
376 return 0;
377 hwc_session->color_mgr_->SetColorModeDetailEnhancer(primary_display);
378 }
379 }
380
381 for (size_t dpy = 0; dpy < num_displays; dpy++) {
382 hwc_display_contents_1_t *content_list = displays[dpy];
383
384 // Drop virtual display composition if virtual display object could not be created
385 // due to HDMI concurrency.
386 if (dpy == HWC_DISPLAY_VIRTUAL && !hwc_session->hwc_display_[HWC_DISPLAY_VIRTUAL]) {
387 CloseAcquireFds(content_list);
388 if (content_list) {
389 content_list->retireFenceFd = -1;
390 }
391
392 continue;
393 }
394
395 if (hwc_session->hwc_display_[dpy]) {
396 hwc_session->hwc_display_[dpy]->Commit(content_list);
397 }
398 CloseAcquireFds(content_list);
399 }
400
401 if (hwc_session->new_bw_mode_) {
402 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
403 hwc_session->new_bw_mode_ = false;
404 if (hwc_session->bw_mode_release_fd_ >= 0) {
405 close(hwc_session->bw_mode_release_fd_);
406 }
407 hwc_session->bw_mode_release_fd_ = dup(content_list->retireFenceFd);
408 }
409
410 // This is only indicative of how many times SurfaceFlinger posts
411 // frames to the display.
412 CALC_FPS();
413
414 // Return 0, else client will go into bad state
415 return 0;
416 }
417
CloseAcquireFds(hwc_display_contents_1_t * content_list)418 void HWCSession::CloseAcquireFds(hwc_display_contents_1_t *content_list) {
419 if (content_list) {
420 for (size_t i = 0; i < content_list->numHwLayers; i++) {
421 int &acquireFenceFd = content_list->hwLayers[i].acquireFenceFd;
422 if (acquireFenceFd >= 0) {
423 close(acquireFenceFd);
424 acquireFenceFd = -1;
425 }
426 }
427
428 int &outbufAcquireFenceFd = content_list->outbufAcquireFenceFd;
429 if (outbufAcquireFenceFd >= 0) {
430 close(outbufAcquireFenceFd);
431 outbufAcquireFenceFd = -1;
432 }
433 }
434 }
435
IsDisplayYUV(int disp)436 bool HWCSession::IsDisplayYUV(int disp) {
437 int error = -EINVAL;
438 bool is_yuv = false;
439 DisplayConfigVariableInfo attributes = {};
440
441 if (disp < 0 || disp >= HWC_NUM_DISPLAY_TYPES || !hwc_display_[disp]) {
442 DLOGE("Invalid input parameters. Display = %d", disp);
443 return is_yuv;
444 }
445
446 uint32_t active_config = 0;
447 error = hwc_display_[disp]->GetActiveDisplayConfig(&active_config);
448 if (!error) {
449 error = hwc_display_[disp]->GetDisplayAttributesForConfig(INT(active_config), &attributes);
450 if (error == 0) {
451 is_yuv = attributes.is_yuv;
452 } else {
453 DLOGW("Error querying display attributes. Display = %d, Config = %d", disp, active_config);
454 }
455 }
456
457 return is_yuv;
458 }
459
EventControl(hwc_composer_device_1 * device,int disp,int event,int enable)460 int HWCSession::EventControl(hwc_composer_device_1 *device, int disp, int event, int enable) {
461 if (!device) {
462 return -EINVAL;
463 }
464
465 HWCSession *hwc_session = static_cast<HWCSession *>(device);
466 int status = -EINVAL;
467 if (hwc_session->hwc_display_[disp]) {
468 status = hwc_session->hwc_display_[disp]->EventControl(event, enable);
469 }
470
471 return status;
472 }
473
SetPowerMode(hwc_composer_device_1 * device,int disp,int mode)474 int HWCSession::SetPowerMode(hwc_composer_device_1 *device, int disp, int mode) {
475 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
476
477 if (!device) {
478 return -EINVAL;
479 }
480
481 HWCSession *hwc_session = static_cast<HWCSession *>(device);
482 int status = -EINVAL;
483 if (hwc_session->hwc_display_[disp]) {
484 status = hwc_session->hwc_display_[disp]->SetPowerMode(mode);
485 }
486
487 return status;
488 }
489
Query(hwc_composer_device_1 * device,int param,int * value)490 int HWCSession::Query(hwc_composer_device_1 *device, int param, int *value) {
491 SCOPE_LOCK(locker_);
492
493 if (!device || !value) {
494 return -EINVAL;
495 }
496
497 int status = 0;
498
499 switch (param) {
500 case HWC_BACKGROUND_LAYER_SUPPORTED:
501 value[0] = 1;
502 break;
503
504 default:
505 status = -EINVAL;
506 }
507
508 return status;
509 }
510
RegisterProcs(hwc_composer_device_1 * device,hwc_procs_t const * procs)511 void HWCSession::RegisterProcs(hwc_composer_device_1 *device, hwc_procs_t const *procs) {
512 SCOPE_LOCK(locker_);
513
514 if (!device || !procs) {
515 return;
516 }
517
518 HWCSession *hwc_session = static_cast<HWCSession *>(device);
519 hwc_session->hwc_procs_ = procs;
520 }
521
Dump(hwc_composer_device_1 * device,char * buffer,int length)522 void HWCSession::Dump(hwc_composer_device_1 *device, char *buffer, int length) {
523 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
524
525 if (!device || !buffer || !length) {
526 return;
527 }
528
529 DumpInterface::GetDump(buffer, UINT32(length));
530 }
531
GetDisplayConfigs(hwc_composer_device_1 * device,int disp,uint32_t * configs,size_t * num_configs)532 int HWCSession::GetDisplayConfigs(hwc_composer_device_1 *device, int disp, uint32_t *configs,
533 size_t *num_configs) {
534 SCOPE_LOCK(locker_);
535
536 if (!device || !configs || !num_configs) {
537 return -EINVAL;
538 }
539
540 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
541 return -EINVAL;
542 }
543
544 HWCSession *hwc_session = static_cast<HWCSession *>(device);
545 int status = -EINVAL;
546 if (hwc_session->hwc_display_[disp]) {
547 status = hwc_session->hwc_display_[disp]->GetDisplayConfigs(configs, num_configs);
548 }
549
550 return status;
551 }
552
GetDisplayAttributes(hwc_composer_device_1 * device,int disp,uint32_t config,const uint32_t * display_attributes,int32_t * values)553 int HWCSession::GetDisplayAttributes(hwc_composer_device_1 *device, int disp, uint32_t config,
554 const uint32_t *display_attributes, int32_t *values) {
555 SCOPE_LOCK(locker_);
556
557 if (!device || !display_attributes || !values) {
558 return -EINVAL;
559 }
560
561 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
562 return -EINVAL;
563 }
564
565 HWCSession *hwc_session = static_cast<HWCSession *>(device);
566 int status = -EINVAL;
567 if (hwc_session->hwc_display_[disp]) {
568 status = hwc_session->hwc_display_[disp]->GetDisplayAttributes(config, display_attributes,
569 values);
570 }
571
572 return status;
573 }
574
GetActiveConfig(hwc_composer_device_1 * device,int disp)575 int HWCSession::GetActiveConfig(hwc_composer_device_1 *device, int disp) {
576 SCOPE_LOCK(locker_);
577
578 if (!device) {
579 return -EINVAL;
580 }
581
582 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
583 return -EINVAL;
584 }
585
586 HWCSession *hwc_session = static_cast<HWCSession *>(device);
587 int active_config = -1;
588 if (hwc_session->hwc_display_[disp]) {
589 active_config = hwc_session->hwc_display_[disp]->GetActiveConfig();
590 }
591
592 return active_config;
593 }
594
SetActiveConfig(hwc_composer_device_1 * device,int disp,int index)595 int HWCSession::SetActiveConfig(hwc_composer_device_1 *device, int disp, int index) {
596 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
597
598 if (!device) {
599 return -EINVAL;
600 }
601
602 if (disp < HWC_DISPLAY_PRIMARY || disp > HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
603 return -EINVAL;
604 }
605
606 HWCSession *hwc_session = static_cast<HWCSession *>(device);
607 int status = -EINVAL;
608
609 if (hwc_session->hwc_display_[disp]) {
610 status = hwc_session->hwc_display_[disp]->SetActiveConfig(index);
611 }
612
613 return status;
614 }
615
SetCursorPositionAsync(hwc_composer_device_1 * device,int disp,int x,int y)616 int HWCSession::SetCursorPositionAsync(hwc_composer_device_1 *device, int disp, int x, int y) {
617 DTRACE_SCOPED();
618
619 SCOPE_LOCK(locker_);
620
621 if (!device || (disp < HWC_DISPLAY_PRIMARY) || (disp > HWC_DISPLAY_VIRTUAL)) {
622 return -EINVAL;
623 }
624
625 int status = -EINVAL;
626 HWCSession *hwc_session = static_cast<HWCSession *>(device);
627 if (hwc_session->hwc_display_[disp]) {
628 status = hwc_session->hwc_display_[disp]->SetCursorPosition(x, y);
629 }
630
631 return status;
632 }
633
ConnectDisplay(int disp,hwc_display_contents_1_t * content_list)634 int HWCSession::ConnectDisplay(int disp, hwc_display_contents_1_t *content_list) {
635 DLOGI("Display = %d", disp);
636
637 int status = 0;
638 uint32_t primary_width = 0;
639 uint32_t primary_height = 0;
640
641 hwc_display_[HWC_DISPLAY_PRIMARY]->GetFrameBufferResolution(&primary_width, &primary_height);
642
643 if (disp == HWC_DISPLAY_EXTERNAL) {
644 status = CreateExternalDisplay(disp, primary_width, primary_height, false);
645 connected_displays_[HWC_DISPLAY_EXTERNAL] = 1;
646 } else if (disp == HWC_DISPLAY_VIRTUAL) {
647 status = HWCDisplayVirtual::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
648 content_list, &hwc_display_[disp]);
649 connected_displays_[HWC_DISPLAY_VIRTUAL] = 1;
650 } else {
651 DLOGE("Invalid display type");
652 return -1;
653 }
654
655 if (!status) {
656 hwc_display_[disp]->SetSecureDisplay(secure_display_active_, true);
657 }
658
659 return status;
660 }
661
DisconnectDisplay(int disp)662 int HWCSession::DisconnectDisplay(int disp) {
663 DLOGI("Display = %d", disp);
664
665 if (disp == HWC_DISPLAY_EXTERNAL) {
666 HWCDisplayExternal::Destroy(hwc_display_[disp]);
667 connected_displays_[HWC_DISPLAY_EXTERNAL] = 0;
668 } else if (disp == HWC_DISPLAY_VIRTUAL) {
669 HWCDisplayVirtual::Destroy(hwc_display_[disp]);
670 connected_displays_[HWC_DISPLAY_VIRTUAL] = 0;
671 } else {
672 DLOGE("Invalid display type");
673 return -1;
674 }
675
676 hwc_display_[disp] = NULL;
677
678 return 0;
679 }
680
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)681 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
682 android::Parcel *output_parcel) {
683 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
684
685 android::status_t status = 0;
686
687 switch (command) {
688 case qService::IQService::DYNAMIC_DEBUG:
689 DynamicDebug(input_parcel);
690 break;
691
692 case qService::IQService::SCREEN_REFRESH:
693 hwc_procs_->invalidate(hwc_procs_);
694 break;
695
696 case qService::IQService::SET_IDLE_TIMEOUT:
697 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
698 uint32_t timeout = UINT32(input_parcel->readInt32());
699 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout);
700 }
701 break;
702
703 case qService::IQService::SET_FRAME_DUMP_CONFIG:
704 SetFrameDumpConfig(input_parcel);
705 break;
706
707 case qService::IQService::SET_MAX_PIPES_PER_MIXER:
708 status = SetMaxMixerStages(input_parcel);
709 break;
710
711 case qService::IQService::SET_DISPLAY_MODE:
712 status = SetDisplayMode(input_parcel);
713 break;
714
715 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS:
716 status = SetSecondaryDisplayStatus(input_parcel, output_parcel);
717 break;
718
719 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
720 status = ConfigureRefreshRate(input_parcel);
721 break;
722
723 case qService::IQService::SET_VIEW_FRAME:
724 break;
725
726 case qService::IQService::TOGGLE_SCREEN_UPDATES:
727 status = ToggleScreenUpdates(input_parcel, output_parcel);
728 break;
729
730 case qService::IQService::QDCM_SVC_CMDS:
731 status = QdcmCMDHandler(input_parcel, output_parcel);
732 break;
733
734 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED:
735 status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel);
736 break;
737
738 case qService::IQService::CONTROL_PARTIAL_UPDATE:
739 status = ControlPartialUpdate(input_parcel, output_parcel);
740 break;
741
742 case qService::IQService::SET_ACTIVE_CONFIG:
743 status = HandleSetActiveDisplayConfig(input_parcel, output_parcel);
744 break;
745
746 case qService::IQService::GET_ACTIVE_CONFIG:
747 status = HandleGetActiveDisplayConfig(input_parcel, output_parcel);
748 break;
749
750 case qService::IQService::GET_CONFIG_COUNT:
751 status = HandleGetDisplayConfigCount(input_parcel, output_parcel);
752 break;
753
754 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
755 status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel);
756 break;
757
758 case qService::IQService::GET_PANEL_BRIGHTNESS:
759 status = GetPanelBrightness(input_parcel, output_parcel);
760 break;
761
762 case qService::IQService::SET_PANEL_BRIGHTNESS:
763 status = SetPanelBrightness(input_parcel, output_parcel);
764 break;
765
766 case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
767 status = GetVisibleDisplayRect(input_parcel, output_parcel);
768 break;
769
770 case qService::IQService::SET_CAMERA_STATUS:
771 status = SetDynamicBWForCamera(input_parcel, output_parcel);
772 break;
773
774 case qService::IQService::GET_BW_TRANSACTION_STATUS:
775 status = GetBWTransactionStatus(input_parcel, output_parcel);
776 break;
777
778 case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
779 status = SetMixerResolution(input_parcel);
780 break;
781
782 case qService::IQService::GET_HDR_CAPABILITIES:
783 status = GetHdrCapabilities(input_parcel, output_parcel);
784 break;
785
786 default:
787 DLOGW("QService command = %d is not supported", command);
788 return -EINVAL;
789 }
790
791 return status;
792 }
793
ToggleScreenUpdates(const android::Parcel * input_parcel,android::Parcel * output_parcel)794 android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel,
795 android::Parcel *output_parcel) {
796 int input = input_parcel->readInt32();
797 int error = android::BAD_VALUE;
798
799 if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) {
800 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1);
801 if (error != 0) {
802 DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error);
803 }
804 }
805 output_parcel->writeInt32(error);
806
807 return error;
808 }
809
SetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)810 android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel,
811 android::Parcel *output_parcel) {
812 int level = input_parcel->readInt32();
813 int error = android::BAD_VALUE;
814
815 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
816 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level);
817 if (error != 0) {
818 DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
819 }
820 }
821 output_parcel->writeInt32(error);
822
823 return error;
824 }
825
GetPanelBrightness(const android::Parcel * input_parcel,android::Parcel * output_parcel)826 android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel,
827 android::Parcel *output_parcel) {
828 int error = android::BAD_VALUE;
829 int ret = error;
830
831 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
832 error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret);
833 if (error != 0) {
834 ret = error;
835 DLOGE("Failed to get the panel brightness. Error = %d", error);
836 }
837 }
838 output_parcel->writeInt32(ret);
839
840 return error;
841 }
842
ControlPartialUpdate(const android::Parcel * input_parcel,android::Parcel * out)843 android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel,
844 android::Parcel *out) {
845 DisplayError error = kErrorNone;
846 int ret = 0;
847 uint32_t disp_id = UINT32(input_parcel->readInt32());
848 uint32_t enable = UINT32(input_parcel->readInt32());
849
850 if (disp_id != HWC_DISPLAY_PRIMARY) {
851 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
852 ret = -EINVAL;
853 out->writeInt32(ret);
854 return ret;
855 }
856
857 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
858 DLOGE("primary display object is not instantiated");
859 ret = -EINVAL;
860 out->writeInt32(ret);
861 return ret;
862 }
863
864 uint32_t pending = 0;
865 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending);
866
867 if (error == kErrorNone) {
868 if (!pending) {
869 out->writeInt32(ret);
870 return ret;
871 }
872 } else if (error == kErrorNotSupported) {
873 out->writeInt32(ret);
874 return ret;
875 } else {
876 ret = -EINVAL;
877 out->writeInt32(ret);
878 return ret;
879 }
880
881 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
882 hwc_procs_->invalidate(hwc_procs_);
883
884 // Wait until partial update control is complete
885 ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
886
887 out->writeInt32(ret);
888
889 return ret;
890 }
891
HandleSetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)892 android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel,
893 android::Parcel *output_parcel) {
894 int config = input_parcel->readInt32();
895 int dpy = input_parcel->readInt32();
896 int error = android::BAD_VALUE;
897
898 if (dpy > HWC_DISPLAY_VIRTUAL) {
899 return android::BAD_VALUE;
900 }
901
902 if (hwc_display_[dpy]) {
903 error = hwc_display_[dpy]->SetActiveDisplayConfig(config);
904 if (error == 0) {
905 hwc_procs_->invalidate(hwc_procs_);
906 }
907 }
908
909 return error;
910 }
911
HandleGetActiveDisplayConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)912 android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel,
913 android::Parcel *output_parcel) {
914 int dpy = input_parcel->readInt32();
915 int error = android::BAD_VALUE;
916
917 if (dpy > HWC_DISPLAY_VIRTUAL) {
918 return android::BAD_VALUE;
919 }
920
921 if (hwc_display_[dpy]) {
922 uint32_t config = 0;
923 error = hwc_display_[dpy]->GetActiveDisplayConfig(&config);
924 if (error == 0) {
925 output_parcel->writeInt32(INT(config));
926 }
927 }
928
929 return error;
930 }
931
HandleGetDisplayConfigCount(const android::Parcel * input_parcel,android::Parcel * output_parcel)932 android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel,
933 android::Parcel *output_parcel) {
934 int dpy = input_parcel->readInt32();
935 int error = android::BAD_VALUE;
936
937 if (dpy > HWC_DISPLAY_VIRTUAL) {
938 return android::BAD_VALUE;
939 }
940
941 uint32_t count = 0;
942 if (hwc_display_[dpy]) {
943 error = hwc_display_[dpy]->GetDisplayConfigCount(&count);
944 if (error == 0) {
945 output_parcel->writeInt32(INT(count));
946 }
947 }
948
949 return error;
950 }
951
SetDisplayPort(DisplayPort sdm_disp_port,int * hwc_disp_port)952 android::status_t HWCSession::SetDisplayPort(DisplayPort sdm_disp_port, int *hwc_disp_port) {
953 if (!hwc_disp_port) {
954 return -EINVAL;
955 }
956
957 switch (sdm_disp_port) {
958 case kPortDSI:
959 *hwc_disp_port = qdutils::DISPLAY_PORT_DSI;
960 break;
961 case kPortDTV:
962 *hwc_disp_port = qdutils::DISPLAY_PORT_DTV;
963 break;
964 case kPortLVDS:
965 *hwc_disp_port = qdutils::DISPLAY_PORT_LVDS;
966 break;
967 case kPortEDP:
968 *hwc_disp_port = qdutils::DISPLAY_PORT_EDP;
969 break;
970 case kPortWriteBack:
971 *hwc_disp_port = qdutils::DISPLAY_PORT_WRITEBACK;
972 break;
973 case kPortDP:
974 *hwc_disp_port = qdutils::DISPLAY_PORT_DP;
975 break;
976 case kPortDefault:
977 *hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
978 break;
979 default:
980 DLOGE("Invalid sdm display port %d", sdm_disp_port);
981 return -EINVAL;
982 }
983
984 return 0;
985 }
986
HandleGetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)987 android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel
988 *input_parcel,
989 android::Parcel *output_parcel) {
990 int config = input_parcel->readInt32();
991 int dpy = input_parcel->readInt32();
992 int error = android::BAD_VALUE;
993 DisplayConfigVariableInfo display_attributes;
994 DisplayPort sdm_disp_port = kPortDefault;
995 int hwc_disp_port = qdutils::DISPLAY_PORT_DEFAULT;
996
997 if (dpy > HWC_DISPLAY_VIRTUAL) {
998 return android::BAD_VALUE;
999 }
1000
1001 if (hwc_display_[dpy]) {
1002 error = hwc_display_[dpy]->GetDisplayAttributesForConfig(config, &display_attributes);
1003 if (error == 0) {
1004 hwc_display_[dpy]->GetDisplayPort(&sdm_disp_port);
1005
1006 SetDisplayPort(sdm_disp_port, &hwc_disp_port);
1007
1008 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1009 output_parcel->writeInt32(INT(display_attributes.x_pixels));
1010 output_parcel->writeInt32(INT(display_attributes.y_pixels));
1011 output_parcel->writeFloat(display_attributes.x_dpi);
1012 output_parcel->writeFloat(display_attributes.y_dpi);
1013 output_parcel->writeInt32(hwc_disp_port);
1014 output_parcel->writeInt32(display_attributes.is_yuv);
1015 }
1016 }
1017
1018 return error;
1019 }
1020
SetSecondaryDisplayStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1021 android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel,
1022 android::Parcel *output_parcel) {
1023 int ret = -EINVAL;
1024
1025 uint32_t display_id = UINT32(input_parcel->readInt32());
1026 uint32_t display_status = UINT32(input_parcel->readInt32());
1027
1028 DLOGI("Display = %d, Status = %d", display_id, display_status);
1029
1030 if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1031 DLOGE("Invalid display_id");
1032 } else if (display_id == HWC_DISPLAY_PRIMARY) {
1033 DLOGE("Not supported for this display");
1034 } else if (!hwc_display_[display_id]) {
1035 DLOGW("Display is not connected");
1036 } else {
1037 ret = hwc_display_[display_id]->SetDisplayStatus(display_status);
1038 }
1039
1040 output_parcel->writeInt32(ret);
1041
1042 return ret;
1043 }
1044
ConfigureRefreshRate(const android::Parcel * input_parcel)1045 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1046 uint32_t operation = UINT32(input_parcel->readInt32());
1047 switch (operation) {
1048 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1049 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1050 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
1051 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1052 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1053 HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
1054 case qdutils::SET_BINDER_DYN_REFRESH_RATE:
1055 {
1056 uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1057 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(
1058 HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE,
1059 refresh_rate);
1060 }
1061 default:
1062 DLOGW("Invalid operation %d", operation);
1063 return -EINVAL;
1064 }
1065
1066 return 0;
1067 }
1068
SetDisplayMode(const android::Parcel * input_parcel)1069 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1070 uint32_t mode = UINT32(input_parcel->readInt32());
1071 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode);
1072 }
1073
SetMaxMixerStages(const android::Parcel * input_parcel)1074 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1075 DisplayError error = kErrorNone;
1076 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1077 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1078
1079 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1080 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1081 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMaxMixerStages(max_mixer_stages);
1082 if (error != kErrorNone) {
1083 return -EINVAL;
1084 }
1085 }
1086 }
1087
1088 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1089 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1090 error = hwc_display_[HWC_DISPLAY_EXTERNAL]->SetMaxMixerStages(max_mixer_stages);
1091 if (error != kErrorNone) {
1092 return -EINVAL;
1093 }
1094 }
1095 }
1096
1097 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1098 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1099 error = hwc_display_[HWC_DISPLAY_VIRTUAL]->SetMaxMixerStages(max_mixer_stages);
1100 if (error != kErrorNone) {
1101 return -EINVAL;
1102 }
1103 }
1104 }
1105
1106 return 0;
1107 }
1108
SetDynamicBWForCamera(const android::Parcel * input_parcel,android::Parcel * output_parcel)1109 android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel,
1110 android::Parcel *output_parcel) {
1111 DisplayError error = kErrorNone;
1112 uint32_t camera_status = UINT32(input_parcel->readInt32());
1113 HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault;
1114
1115 // trigger invalidate to apply new bw caps.
1116 hwc_procs_->invalidate(hwc_procs_);
1117
1118 error = core_intf_->SetMaxBandwidthMode(mode);
1119 if (error != kErrorNone) {
1120 return -EINVAL;
1121 }
1122
1123 new_bw_mode_ = true;
1124 need_invalidate_ = true;
1125
1126 return 0;
1127 }
1128
GetBWTransactionStatus(const android::Parcel * input_parcel,android::Parcel * output_parcel)1129 android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel,
1130 android::Parcel *output_parcel) {
1131 bool state = true;
1132
1133 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1134 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
1135 DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno));
1136 state = false;
1137 }
1138 output_parcel->writeInt32(state);
1139 }
1140
1141 return 0;
1142 }
1143
SetFrameDumpConfig(const android::Parcel * input_parcel)1144 void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1145 uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1146 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1147 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1148
1149 if (bit_mask_display_type[HWC_DISPLAY_PRIMARY]) {
1150 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1151 hwc_display_[HWC_DISPLAY_PRIMARY]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1152 }
1153 }
1154
1155 if (bit_mask_display_type[HWC_DISPLAY_EXTERNAL]) {
1156 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1157 hwc_display_[HWC_DISPLAY_EXTERNAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1158 }
1159 }
1160
1161 if (bit_mask_display_type[HWC_DISPLAY_VIRTUAL]) {
1162 if (hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1163 hwc_display_[HWC_DISPLAY_VIRTUAL]->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type);
1164 }
1165 }
1166 }
1167
SetMixerResolution(const android::Parcel * input_parcel)1168 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1169 DisplayError error = kErrorNone;
1170 uint32_t dpy = UINT32(input_parcel->readInt32());
1171
1172 if (dpy != HWC_DISPLAY_PRIMARY) {
1173 DLOGI("Resoulution change not supported for this display %d", dpy);
1174 return -EINVAL;
1175 }
1176
1177 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1178 DLOGI("Primary display is not initialized");
1179 return -EINVAL;
1180 }
1181
1182 uint32_t width = UINT32(input_parcel->readInt32());
1183 uint32_t height = UINT32(input_parcel->readInt32());
1184
1185 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1186 if (error != kErrorNone) {
1187 return -EINVAL;
1188 }
1189
1190 return 0;
1191 }
1192
GetHdrCapabilities(const android::Parcel * input_parcel,android::Parcel * output_parcel)1193 android::status_t HWCSession::GetHdrCapabilities(const android::Parcel *input_parcel,
1194 android::Parcel *output_parcel) {
1195 uint32_t display_id = UINT32(input_parcel->readInt32());
1196 if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1197 DLOGE("Invalid display id = %d", display_id);
1198 return -EINVAL;
1199 }
1200
1201 if (hwc_display_[display_id] == NULL) {
1202 DLOGW("Display = %d not initialized", display_id);
1203 return -EINVAL;
1204 }
1205
1206 DisplayConfigFixedInfo fixed_info = {};
1207 int ret = hwc_display_[display_id]->GetDisplayFixedConfig(&fixed_info);
1208 if (ret) {
1209 DLOGE("Failed");
1210 return ret;
1211 }
1212
1213 if (!fixed_info.hdr_supported) {
1214 DLOGI("HDR is not supported");
1215 return 0;
1216 }
1217
1218 std::vector<int32_t> supported_hdr_types = {};
1219 // Only HDR10 supported now, in future add other supported HDR formats(HLG, DolbyVision)
1220 supported_hdr_types.push_back(HAL_HDR_HDR10);
1221
1222 static const float kLuminanceFactor = 10000.0;
1223 // luminance is expressed in the unit of 0.0001 cd/m2, convert it to 1cd/m2.
1224 float max_luminance = FLOAT(fixed_info.max_luminance)/kLuminanceFactor;
1225 float max_average_luminance = FLOAT(fixed_info.average_luminance)/kLuminanceFactor;
1226 float min_luminance = FLOAT(fixed_info.min_luminance)/kLuminanceFactor;
1227
1228 if (output_parcel != nullptr) {
1229 output_parcel->writeInt32Vector(supported_hdr_types);
1230 output_parcel->writeFloat(max_luminance);
1231 output_parcel->writeFloat(max_average_luminance);
1232 output_parcel->writeFloat(min_luminance);
1233 }
1234
1235 return 0;
1236 }
1237
DynamicDebug(const android::Parcel * input_parcel)1238 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
1239 int type = input_parcel->readInt32();
1240 bool enable = (input_parcel->readInt32() > 0);
1241 DLOGI("type = %d enable = %d", type, enable);
1242 int verbose_level = input_parcel->readInt32();
1243
1244 switch (type) {
1245 case qService::IQService::DEBUG_ALL:
1246 HWCDebugHandler::DebugAll(enable, verbose_level);
1247 break;
1248
1249 case qService::IQService::DEBUG_MDPCOMP:
1250 HWCDebugHandler::DebugStrategy(enable, verbose_level);
1251 HWCDebugHandler::DebugCompManager(enable, verbose_level);
1252 break;
1253
1254 case qService::IQService::DEBUG_PIPE_LIFECYCLE:
1255 HWCDebugHandler::DebugResources(enable, verbose_level);
1256 break;
1257
1258 case qService::IQService::DEBUG_DRIVER_CONFIG:
1259 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1260 break;
1261
1262 case qService::IQService::DEBUG_ROTATOR:
1263 HWCDebugHandler::DebugResources(enable, verbose_level);
1264 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
1265 HWCDebugHandler::DebugRotator(enable, verbose_level);
1266 break;
1267
1268 case qService::IQService::DEBUG_QDCM:
1269 HWCDebugHandler::DebugQdcm(enable, verbose_level);
1270 break;
1271
1272 default:
1273 DLOGW("type = %d is not supported", type);
1274 }
1275 }
1276
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)1277 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
1278 android::Parcel *output_parcel) {
1279 int ret = 0;
1280 int32_t *brightness_value = NULL;
1281 uint32_t display_id(0);
1282 PPPendingParams pending_action;
1283 PPDisplayAPIPayload resp_payload, req_payload;
1284
1285 if (!color_mgr_) {
1286 return -1;
1287 }
1288
1289 pending_action.action = kNoAction;
1290 pending_action.params = NULL;
1291
1292 // Read display_id, payload_size and payload from in_parcel.
1293 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
1294 if (!ret) {
1295 if (HWC_DISPLAY_PRIMARY == display_id && hwc_display_[HWC_DISPLAY_PRIMARY])
1296 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->ColorSVCRequestRoute(req_payload,
1297 &resp_payload, &pending_action);
1298
1299 if (HWC_DISPLAY_EXTERNAL == display_id && hwc_display_[HWC_DISPLAY_EXTERNAL])
1300 ret = hwc_display_[HWC_DISPLAY_EXTERNAL]->ColorSVCRequestRoute(req_payload, &resp_payload,
1301 &pending_action);
1302 }
1303
1304 if (ret) {
1305 output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
1306 req_payload.DestroyPayload();
1307 resp_payload.DestroyPayload();
1308 return ret;
1309 }
1310
1311 switch (pending_action.action) {
1312 case kInvalidating:
1313 hwc_procs_->invalidate(hwc_procs_);
1314 break;
1315 case kEnterQDCMMode:
1316 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1317 break;
1318 case kExitQDCMMode:
1319 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1320 break;
1321 case kApplySolidFill:
1322 ret = color_mgr_->SetSolidFill(pending_action.params,
1323 true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1324 hwc_procs_->invalidate(hwc_procs_);
1325 break;
1326 case kDisableSolidFill:
1327 ret = color_mgr_->SetSolidFill(pending_action.params,
1328 false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1329 hwc_procs_->invalidate(hwc_procs_);
1330 break;
1331 case kSetPanelBrightness:
1332 brightness_value = reinterpret_cast<int32_t*>(resp_payload.payload);
1333 if (brightness_value == NULL) {
1334 DLOGE("Brightness value is Null");
1335 return -EINVAL;
1336 }
1337 if (HWC_DISPLAY_PRIMARY == display_id)
1338 ret = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(*brightness_value);
1339 break;
1340 case kEnableFrameCapture:
1341 ret = color_mgr_->SetFrameCapture(pending_action.params,
1342 true, hwc_display_[HWC_DISPLAY_PRIMARY]);
1343 hwc_procs_->invalidate(hwc_procs_);
1344 break;
1345 case kDisableFrameCapture:
1346 ret = color_mgr_->SetFrameCapture(pending_action.params,
1347 false, hwc_display_[HWC_DISPLAY_PRIMARY]);
1348 break;
1349 case kConfigureDetailedEnhancer:
1350 ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
1351 hwc_display_[HWC_DISPLAY_PRIMARY]);
1352 hwc_procs_->invalidate(hwc_procs_);
1353 break;
1354 case kNoAction:
1355 break;
1356 default:
1357 DLOGW("Invalid pending action = %d!", pending_action.action);
1358 break;
1359 }
1360
1361 // for display API getter case, marshall returned params into out_parcel.
1362 output_parcel->writeInt32(ret);
1363 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
1364 req_payload.DestroyPayload();
1365 resp_payload.DestroyPayload();
1366
1367 return (ret? -EINVAL : 0);
1368 }
1369
OnMinHdcpEncryptionLevelChange(const android::Parcel * input_parcel,android::Parcel * output_parcel)1370 android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel,
1371 android::Parcel *output_parcel) {
1372 int ret = -EINVAL;
1373 uint32_t display_id = UINT32(input_parcel->readInt32());
1374 uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1375
1376 DLOGI("Display %d", display_id);
1377
1378 if (display_id >= HWC_NUM_DISPLAY_TYPES) {
1379 DLOGE("Invalid display_id");
1380 } else if (display_id != HWC_DISPLAY_EXTERNAL) {
1381 DLOGE("Not supported for display");
1382 } else if (!hwc_display_[display_id]) {
1383 DLOGW("Display is not connected");
1384 } else {
1385 ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
1386 }
1387
1388 output_parcel->writeInt32(ret);
1389
1390 return ret;
1391 }
1392
HWCUeventThread(void * context)1393 void* HWCSession::HWCUeventThread(void *context) {
1394 if (context) {
1395 return reinterpret_cast<HWCSession *>(context)->HWCUeventThreadHandler();
1396 }
1397
1398 return NULL;
1399 }
1400
HWCUeventThreadHandler()1401 void* HWCSession::HWCUeventThreadHandler() {
1402 static char uevent_data[PAGE_SIZE];
1403 int length = 0;
1404 prctl(PR_SET_NAME, uevent_thread_name_, 0, 0, 0);
1405 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1406 if (!uevent_init()) {
1407 DLOGE("Failed to init uevent");
1408 pthread_exit(0);
1409 return NULL;
1410 }
1411
1412 while (!uevent_thread_exit_) {
1413 // keep last 2 zeroes to ensure double 0 termination
1414 length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
1415
1416 if (strcasestr(HWC_UEVENT_SWITCH_HDMI, uevent_data)) {
1417 DLOGI("Uevent HDMI = %s", uevent_data);
1418 int connected = GetEventValue(uevent_data, length, "SWITCH_STATE=");
1419 if (connected >= 0) {
1420 DLOGI("HDMI = %s", connected ? "connected" : "disconnected");
1421 if (HotPlugHandler(connected) == -1) {
1422 DLOGE("Failed handling Hotplug = %s", connected ? "connected" : "disconnected");
1423 }
1424 }
1425 } else if (strcasestr(HWC_UEVENT_GRAPHICS_FB0, uevent_data)) {
1426 DLOGI("Uevent FB0 = %s", uevent_data);
1427 int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
1428 if (panel_reset == 0) {
1429 if (hwc_procs_) {
1430 reset_panel_ = true;
1431 hwc_procs_->invalidate(hwc_procs_);
1432 } else {
1433 DLOGW("Ignore resetpanel - hwc_proc not registered");
1434 }
1435 }
1436 }
1437 }
1438 pthread_exit(0);
1439
1440 return NULL;
1441 }
1442
GetEventValue(const char * uevent_data,int length,const char * event_info)1443 int HWCSession::GetEventValue(const char *uevent_data, int length, const char *event_info) {
1444 const char *iterator_str = uevent_data;
1445 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
1446 const char *pstr = strstr(iterator_str, event_info);
1447 if (pstr != NULL) {
1448 return (atoi(iterator_str + strlen(event_info)));
1449 }
1450 iterator_str += strlen(iterator_str) + 1;
1451 }
1452
1453 return -1;
1454 }
1455
ResetPanel()1456 void HWCSession::ResetPanel() {
1457 int status = -EINVAL;
1458
1459 DLOGI("Powering off primary");
1460 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_OFF);
1461 if (status) {
1462 DLOGE("power-off on primary failed with error = %d", status);
1463 }
1464
1465 DLOGI("Restoring power mode on primary");
1466 int32_t mode = INT(hwc_display_[HWC_DISPLAY_PRIMARY]->GetLastPowerMode());
1467 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(mode);
1468 if (status) {
1469 DLOGE("Setting power mode = %d on primary failed with error = %d", mode, status);
1470 }
1471
1472 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, 1);
1473 if (status) {
1474 DLOGE("enabling vsync failed for primary with error = %d", status);
1475 }
1476
1477 reset_panel_ = false;
1478 }
1479
HotPlugHandler(bool connected)1480 int HWCSession::HotPlugHandler(bool connected) {
1481 int status = 0;
1482 bool notify_hotplug = false;
1483 bool refresh_screen = false;
1484
1485 // To prevent sending events to client while a lock is held, acquire scope locks only within
1486 // below scope so that those get automatically unlocked after the scope ends.
1487 {
1488 SEQUENCE_WAIT_SCOPE_LOCK(locker_);
1489
1490 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1491 DLOGE("Primay display is not connected.");
1492 return -1;
1493 }
1494
1495
1496 HWCDisplay *primary_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1497 HWCDisplay *external_display = NULL;
1498 HWCDisplay *null_display = NULL;
1499
1500 if (primary_display->GetDisplayClass() == DISPLAY_CLASS_EXTERNAL) {
1501 external_display = static_cast<HWCDisplayExternal *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1502 } else if (primary_display->GetDisplayClass() == DISPLAY_CLASS_NULL) {
1503 null_display = static_cast<HWCDisplayNull *>(hwc_display_[HWC_DISPLAY_PRIMARY]);
1504 }
1505
1506 // If primary display connected is a NULL display, then replace it with the external display
1507 if (connected) {
1508 // If we are in HDMI as primary and the primary display just got plugged in
1509 if (is_hdmi_primary_ && null_display) {
1510 uint32_t primary_width, primary_height;
1511 int status = 0;
1512 null_display->GetFrameBufferResolution(&primary_width, &primary_height);
1513 delete null_display;
1514 hwc_display_[HWC_DISPLAY_PRIMARY] = NULL;
1515
1516 // Create external display with a forced framebuffer resolution to that of what the NULL
1517 // display had. This is necessary because SurfaceFlinger does not dynamically update
1518 // framebuffer resolution once it reads it at bootup. So we always have to have the NULL
1519 // display/external display both at the bootup resolution.
1520 status = CreateExternalDisplay(HWC_DISPLAY_PRIMARY, primary_width, primary_height, true);
1521 if (status) {
1522 DLOGE("Could not create external display");
1523 return -1;
1524 }
1525
1526 status = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPowerMode(HWC_POWER_MODE_NORMAL);
1527 if (status) {
1528 DLOGE("power-on on primary failed with error = %d", status);
1529 }
1530
1531 is_hdmi_yuv_ = IsDisplayYUV(HWC_DISPLAY_PRIMARY);
1532
1533 // Next, go ahead and enable vsync on external display. This is expliclity required
1534 // because in HDMI as primary case, SurfaceFlinger may not be aware of underlying
1535 // changing display. and thus may not explicitly enable vsync
1536
1537 status = hwc_display_[HWC_DISPLAY_PRIMARY]->EventControl(HWC_EVENT_VSYNC, true);
1538 if (status) {
1539 DLOGE("Error enabling vsync for HDMI as primary case");
1540 }
1541 // Don't do hotplug notification for HDMI as primary case for now
1542 notify_hotplug = false;
1543 refresh_screen = true;
1544 } else {
1545 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1546 DLOGE("HDMI is already connected");
1547 return -1;
1548 }
1549
1550 // Connect external display if virtual display is not connected.
1551 // Else, defer external display connection and process it when virtual display
1552 // tears down; Do not notify SurfaceFlinger since connection is deferred now.
1553 if (!hwc_display_[HWC_DISPLAY_VIRTUAL]) {
1554 status = ConnectDisplay(HWC_DISPLAY_EXTERNAL, NULL);
1555 if (status) {
1556 return status;
1557 }
1558 notify_hotplug = true;
1559 } else {
1560 DLOGI("Virtual display is connected, pending connection");
1561 external_pending_connect_ = true;
1562 }
1563 }
1564 } else {
1565 // Do not return error if external display is not in connected status.
1566 // Due to virtual display concurrency, external display connection might be still pending
1567 // but hdmi got disconnected before pending connection could be processed.
1568
1569 if (is_hdmi_primary_ && external_display) {
1570 uint32_t x_res, y_res;
1571 external_display->GetFrameBufferResolution(&x_res, &y_res);
1572 // Need to manually disable VSYNC as SF is not aware of connect/disconnect cases
1573 // for HDMI as primary
1574 external_display->EventControl(HWC_EVENT_VSYNC, false);
1575 HWCDisplayExternal::Destroy(external_display);
1576
1577 HWCDisplayNull *null_display;
1578
1579 int status = HWCDisplayNull::Create(core_intf_, &hwc_procs_,
1580 reinterpret_cast<HWCDisplay **>(&null_display));
1581
1582 if (status) {
1583 DLOGE("Could not create Null display when primary got disconnected");
1584 return -1;
1585 }
1586
1587 null_display->SetResolution(x_res, y_res);
1588 hwc_display_[HWC_DISPLAY_PRIMARY] = null_display;
1589
1590 // Don't do hotplug notification for HDMI as primary case for now
1591 notify_hotplug = false;
1592 } else {
1593 if (hwc_display_[HWC_DISPLAY_EXTERNAL]) {
1594 status = DisconnectDisplay(HWC_DISPLAY_EXTERNAL);
1595 notify_hotplug = true;
1596 }
1597 external_pending_connect_ = false;
1598 }
1599 }
1600 }
1601
1602 if (connected && (notify_hotplug || refresh_screen)) {
1603 // trigger screen refresh to ensure sufficient resources are available to process new
1604 // new display connection.
1605 hwc_procs_->invalidate(hwc_procs_);
1606 uint32_t vsync_period = UINT32(GetVsyncPeriod(HWC_DISPLAY_PRIMARY));
1607 usleep(vsync_period * 2 / 1000);
1608 }
1609 // notify client
1610 if (notify_hotplug) {
1611 hwc_procs_->hotplug(hwc_procs_, HWC_DISPLAY_EXTERNAL, connected);
1612 }
1613
1614 qservice_->onHdmiHotplug(INT(connected));
1615
1616 return 0;
1617 }
1618
HandleSecureDisplaySession(hwc_display_contents_1_t ** displays)1619 void HWCSession::HandleSecureDisplaySession(hwc_display_contents_1_t **displays) {
1620 secure_display_active_ = false;
1621 if (!*displays) {
1622 DLOGW("Invalid display contents");
1623 return;
1624 }
1625
1626 hwc_display_contents_1_t *content_list = displays[HWC_DISPLAY_PRIMARY];
1627 if (!content_list) {
1628 DLOGW("Invalid primary content list");
1629 return;
1630 }
1631 size_t num_hw_layers = content_list->numHwLayers;
1632
1633 for (size_t i = 0; i < num_hw_layers - 1; i++) {
1634 hwc_layer_1_t &hwc_layer = content_list->hwLayers[i];
1635 const private_handle_t *pvt_handle = static_cast<const private_handle_t *>(hwc_layer.handle);
1636 if (pvt_handle && pvt_handle->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY) {
1637 secure_display_active_ = true;
1638 }
1639 }
1640
1641 // Force flush on primary during transitions(secure<->non secure)
1642 // when external displays are connected.
1643 bool force_flush = false;
1644 if ((connected_displays_[HWC_DISPLAY_PRIMARY] == 1) &&
1645 ((connected_displays_[HWC_DISPLAY_EXTERNAL] == 1) ||
1646 (connected_displays_[HWC_DISPLAY_VIRTUAL] == 1))) {
1647 force_flush = true;
1648 }
1649
1650 for (ssize_t dpy = static_cast<ssize_t>(HWC_NUM_DISPLAY_TYPES - 1); dpy >= 0; dpy--) {
1651 if (hwc_display_[dpy]) {
1652 hwc_display_[dpy]->SetSecureDisplay(secure_display_active_, force_flush);
1653 }
1654 }
1655 }
1656
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)1657 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
1658 android::Parcel *output_parcel) {
1659 int dpy = input_parcel->readInt32();
1660
1661 if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) {
1662 return android::BAD_VALUE;;
1663 }
1664
1665 if (!hwc_display_[dpy]) {
1666 return android::NO_INIT;
1667 }
1668
1669 hwc_rect_t visible_rect = {0, 0, 0, 0};
1670 int error = hwc_display_[dpy]->GetVisibleDisplayRect(&visible_rect);
1671 if (error < 0) {
1672 return error;
1673 }
1674
1675 output_parcel->writeInt32(visible_rect.left);
1676 output_parcel->writeInt32(visible_rect.top);
1677 output_parcel->writeInt32(visible_rect.right);
1678 output_parcel->writeInt32(visible_rect.bottom);
1679
1680 return android::NO_ERROR;
1681 }
1682
CreateExternalDisplay(int disp,uint32_t primary_width,uint32_t primary_height,bool use_primary_res)1683 int HWCSession::CreateExternalDisplay(int disp, uint32_t primary_width, uint32_t primary_height,
1684 bool use_primary_res) {
1685 uint32_t panel_bpp = 0;
1686 uint32_t pattern_type = 0;
1687
1688 if (qdutils::isDPConnected()) {
1689 qdutils::getDPTestConfig(&panel_bpp, &pattern_type);
1690 }
1691
1692 if (panel_bpp && pattern_type) {
1693 return HWCDisplayExternalTest::Create(core_intf_, &hwc_procs_, qservice_, panel_bpp,
1694 pattern_type, &hwc_display_[disp]);
1695 }
1696
1697 return HWCDisplayExternal::Create(core_intf_, &hwc_procs_, primary_width, primary_height,
1698 qservice_, use_primary_res, &hwc_display_[disp]);
1699 }
1700
1701 } // namespace sdm
1702
1703