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