1 /*
2 * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
3 * Not a Contribution.
4 *
5 * Copyright 2015 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #include <QService.h>
21 #include <binder/Parcel.h>
22 #include <core/buffer_allocator.h>
23 #include <cutils/properties.h>
24 #include <display_config.h>
25 #include <hardware_legacy/uevent.h>
26 #include <private/color_params.h>
27 #include <qd_utils.h>
28 #include <sync/sync.h>
29 #include <sys/prctl.h>
30 #include <sys/resource.h>
31 #include <utils/String16.h>
32 #include <utils/constants.h>
33 #include <utils/debug.h>
34 #include <QService.h>
35 #include <utils/utils.h>
36 #include <algorithm>
37 #include <utility>
38 #include <bitset>
39 #include <iterator>
40 #include <memory>
41 #include <string>
42 #include <thread>
43 #include <vector>
44 #include <cutils/sockets.h>
45
46 #include "hwc_buffer_allocator.h"
47 #include "hwc_session.h"
48 #include "hwc_debugger.h"
49
50 #define __CLASS__ "HWCSession"
51
52 #define HWC_UEVENT_SWITCH_HDMI "change@/devices/virtual/switch/hdmi"
53 #define HWC_UEVENT_DRM_EXT_HOTPLUG "mdss_mdp/drm/card"
54
55 using HwcAttribute = composer_V2_4::IComposerClient::Attribute;
56 extern void DisplayInit(sdm::HWCSession *hwc_session);
57
58 namespace sdm {
59
60 static HWCUEvent g_hwc_uevent_;
61 Locker HWCSession::locker_[HWCCallbacks::kNumDisplays];
62 bool HWCSession::pending_power_mode_[HWCCallbacks::kNumDisplays];
63 Locker HWCSession::power_state_[HWCCallbacks::kNumDisplays];
64 Locker HWCSession::hdr_locker_[HWCCallbacks::kNumDisplays];
65 Locker HWCSession::display_config_locker_;
66 Locker HWCSession::system_locker_;
67 static const int kSolidFillDelay = 100 * 1000;
68 int HWCSession::null_display_mode_ = 0;
69 static const uint32_t kBrightnessScaleMax = 100;
70 static const uint32_t kSvBlScaleMax = 65535;
71
72 // Map the known color modes to dataspace.
GetDataspaceFromColorMode(ColorMode mode)73 int32_t GetDataspaceFromColorMode(ColorMode mode) {
74 switch (mode) {
75 case ColorMode::SRGB:
76 case ColorMode::NATIVE:
77 return HAL_DATASPACE_V0_SRGB;
78 case ColorMode::DCI_P3:
79 return HAL_DATASPACE_DCI_P3;
80 case ColorMode::DISPLAY_P3:
81 return HAL_DATASPACE_DISPLAY_P3;
82 case ColorMode::BT2100_PQ:
83 return HAL_DATASPACE_BT2020_PQ;
84 case ColorMode::BT2100_HLG:
85 return HAL_DATASPACE_BT2020_HLG;
86 case ColorMode::DISPLAY_BT2020:
87 return HAL_DATASPACE_DISPLAY_BT2020;
88 default:
89 return HAL_DATASPACE_UNKNOWN;
90 }
91 }
92
UEventThread(HWCUEvent * hwc_uevent)93 void HWCUEvent::UEventThread(HWCUEvent *hwc_uevent) {
94 const char *uevent_thread_name = "HWC_UeventThread";
95
96 prctl(PR_SET_NAME, uevent_thread_name, 0, 0, 0);
97 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
98
99 int status = uevent_init();
100 if (!status) {
101 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
102 hwc_uevent->caller_cv_.notify_one();
103 DLOGE("Failed to init uevent with err %d", status);
104 return;
105 }
106
107 {
108 // Signal caller thread that worker thread is ready to listen to events.
109 std::unique_lock<std::mutex> caller_lock(hwc_uevent->mutex_);
110 hwc_uevent->init_done_ = true;
111 hwc_uevent->caller_cv_.notify_one();
112 }
113
114 while (1) {
115 char uevent_data[PAGE_SIZE] = {};
116
117 // keep last 2 zeros to ensure double 0 termination
118 int length = uevent_next_event(uevent_data, INT32(sizeof(uevent_data)) - 2);
119
120 // scope of lock to this block only, so that caller is free to set event handler to nullptr;
121 {
122 std::lock_guard<std::mutex> guard(hwc_uevent->mutex_);
123 if (hwc_uevent->uevent_listener_) {
124 hwc_uevent->uevent_listener_->UEventHandler(uevent_data, length);
125 } else {
126 DLOGW("UEvent dropped. No uevent listener.");
127 }
128 }
129 }
130 }
131
HWCUEvent()132 HWCUEvent::HWCUEvent() {
133 std::unique_lock<std::mutex> caller_lock(mutex_);
134 std::thread thread(HWCUEvent::UEventThread, this);
135 thread.detach();
136 caller_cv_.wait(caller_lock);
137 }
138
Register(HWCUEventListener * uevent_listener)139 void HWCUEvent::Register(HWCUEventListener *uevent_listener) {
140 DLOGI("Set uevent listener = %p", uevent_listener);
141
142 std::lock_guard<std::mutex> obj(mutex_);
143 uevent_listener_ = uevent_listener;
144 }
145
HWCSession()146 HWCSession::HWCSession() : cwb_(this) {}
147
GetInstance()148 HWCSession *HWCSession::GetInstance() {
149 // executed only once for the very first call.
150 // GetInstance called multiple times from Composer and ComposerClient
151 static HWCSession *hwc_session = new HWCSession();
152 return hwc_session;
153 }
154
Init()155 int HWCSession::Init() {
156 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
157
158 int status = -EINVAL;
159 const char *qservice_name = "display.qservice";
160
161 if (!g_hwc_uevent_.InitDone()) {
162 return status;
163 }
164
165
166 // Start QService and connect to it.
167 qService::QService::init();
168 android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(
169 android::defaultServiceManager()->getService(android::String16(qservice_name)));
170
171 if (iqservice.get()) {
172 iqservice->connect(android::sp<qClient::IQClient>(this));
173 qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());
174 } else {
175 DLOGE("Failed to acquire %s", qservice_name);
176 return -EINVAL;
177 }
178
179 DisplayInit(this);
180
181 HWCDebugHandler::Get()->GetProperty(ENABLE_NULL_DISPLAY_PROP, &null_display_mode_);
182 HWCDebugHandler::Get()->GetProperty(DISABLE_HOTPLUG_BWCHECK, &disable_hotplug_bwcheck_);
183 HWCDebugHandler::Get()->GetProperty(DISABLE_MASK_LAYER_HINT, &disable_mask_layer_hint_);
184 HWCDebugHandler::Get()->GetProperty(LBE_SUPPORTED, &is_lbe_supported_);
185
186 if (!null_display_mode_) {
187 g_hwc_uevent_.Register(this);
188 }
189
190 int value = 0; // Default value when property is not present.
191 Debug::Get()->GetProperty(ENABLE_ASYNC_POWERMODE, &value);
192 async_powermode_ = (value == 1);
193 DLOGI("builtin_powermode_override: %d", async_powermode_);
194
195 value = 0;
196 Debug::Get()->GetProperty(ENABLE_ASYNC_VDS_CREATION, &value);
197 async_vds_creation_ = (value == 1);
198 DLOGI("async_vds_creation: %d", async_vds_creation_);
199
200 InitSupportedDisplaySlots();
201 // Create primary display here. Remaining builtin displays will be created after client has set
202 // display indexes which may happen sometime before callback is registered.
203 status = CreatePrimaryDisplay();
204 if (status) {
205 Deinit();
206 return status;
207 }
208
209 is_composer_up_ = true;
210 StartServices();
211
212 PostInit();
213
214 return 0;
215 }
216
PostInit()217 void HWCSession::PostInit() {
218 if (null_display_mode_) {
219 return;
220 }
221
222 // Start services which need IDisplayConfig to be up.
223 // This avoids deadlock between composer and its clients.
224 auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
225 hwc_display->PostInit();
226 }
227
Deinit()228 int HWCSession::Deinit() {
229 if (pps_socket_ >= 0)
230 close(pps_socket_);
231
232 // Destroy all connected displays
233 DestroyDisplay(&map_info_primary_);
234
235 for (auto &map_info : map_info_builtin_) {
236 DestroyDisplay(&map_info);
237 }
238
239 for (auto &map_info : map_info_pluggable_) {
240 DestroyDisplay(&map_info);
241 }
242
243 for (auto &map_info : map_info_virtual_) {
244 DestroyDisplay(&map_info);
245 }
246
247 if (color_mgr_) {
248 color_mgr_->DestroyColorManager();
249 }
250
251 if (!null_display_mode_) {
252 g_hwc_uevent_.Register(nullptr);
253
254 DisplayError error = CoreInterface::DestroyCore();
255 if (error != kErrorNone) {
256 DLOGE("Display core de-initialization failed. Error = %d", error);
257 }
258 }
259
260 return 0;
261 }
262
InitSupportedDisplaySlots()263 void HWCSession::InitSupportedDisplaySlots() {
264 // Default slots:
265 // Primary = 0, External = 1
266 // Additional external displays 2,3,...max_pluggable_count.
267 // Additional builtin displays max_pluggable_count + 1, max_pluggable_count + 2,...
268 // Last slots for virtual displays.
269 // Virtual display id is only for SF <--> HWC communication.
270 // It need not align with hwccomposer_defs
271
272 map_info_primary_.client_id = qdutils::DISPLAY_PRIMARY;
273
274 if (null_display_mode_) {
275 InitSupportedNullDisplaySlots();
276 return;
277 }
278
279 DisplayError error = CoreInterface::CreateCore(&buffer_allocator_, nullptr,
280 &socket_handler_, &core_intf_);
281 if (error != kErrorNone) {
282 DLOGE("Failed to create CoreInterface");
283 return;
284 }
285
286 HWDisplayInterfaceInfo hw_disp_info = {};
287 error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);
288 if (error != kErrorNone) {
289 CoreInterface::DestroyCore();
290 DLOGE("Primary display type not recognized. Error = %d", error);
291 return;
292 }
293
294 int max_builtin = 0;
295 int max_pluggable = 0;
296 int max_virtual = 0;
297
298 error = core_intf_->GetMaxDisplaysSupported(kBuiltIn, &max_builtin);
299 if (error != kErrorNone) {
300 CoreInterface::DestroyCore();
301 DLOGE("Could not find maximum built-in displays supported. Error = %d", error);
302 return;
303 }
304
305 error = core_intf_->GetMaxDisplaysSupported(kPluggable, &max_pluggable);
306 if (error != kErrorNone) {
307 CoreInterface::DestroyCore();
308 DLOGE("Could not find maximum pluggable displays supported. Error = %d", error);
309 return;
310 }
311
312 error = core_intf_->GetMaxDisplaysSupported(kVirtual, &max_virtual);
313 if (error != kErrorNone) {
314 CoreInterface::DestroyCore();
315 DLOGE("Could not find maximum virtual displays supported. Error = %d", error);
316 return;
317 }
318
319 if (max_virtual == 0) {
320 // Check if WB using GPU is supported.
321 max_virtual += virtual_display_factory_.IsGPUColorConvertSupported() ? 1 : 0;
322 }
323
324 if (kPluggable == hw_disp_info.type) {
325 // If primary is a pluggable display, we have already used one pluggable display interface.
326 max_pluggable--;
327 } else {
328 max_builtin--;
329 }
330
331 // Init slots in accordance to h/w capability.
332 uint32_t disp_count = UINT32(std::min(max_pluggable, HWCCallbacks::kNumPluggable));
333 hwc2_display_t base_id = qdutils::DISPLAY_EXTERNAL;
334 map_info_pluggable_.resize(disp_count);
335 for (auto &map_info : map_info_pluggable_) {
336 map_info.client_id = base_id++;
337 }
338
339 disp_count = UINT32(std::min(max_builtin, HWCCallbacks::kNumBuiltIn));
340 map_info_builtin_.resize(disp_count);
341 for (auto &map_info : map_info_builtin_) {
342 map_info.client_id = base_id++;
343 }
344
345 disp_count = UINT32(std::min(max_virtual, HWCCallbacks::kNumVirtual));
346 map_info_virtual_.resize(disp_count);
347 for (auto &map_info : map_info_virtual_) {
348 map_info.client_id = base_id++;
349 }
350
351 // resize HDR supported map to total number of displays.
352 is_hdr_display_.resize(UINT32(base_id));
353
354 if (!async_powermode_) {
355 return;
356 }
357
358 int start_index = HWCCallbacks::kNumRealDisplays;
359 std::vector<DisplayMapInfo> map_info = {map_info_primary_};
360 std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
361 std::copy(map_info_pluggable_.begin(), map_info_pluggable_.end(), std::back_inserter(map_info));
362 for (auto &map : map_info) {
363 DLOGI("Display Pairs: map.client_id: %d, start_index: %d", INT32(map.client_id),
364 INT32(start_index));
365 map_hwc_display_.insert(std::make_pair(map.client_id, start_index++));
366 }
367 }
368
InitSupportedNullDisplaySlots()369 void HWCSession::InitSupportedNullDisplaySlots() {
370 if (!null_display_mode_) {
371 DLOGE("Should only be invoked during null display");
372 return;
373 }
374
375 map_info_primary_.client_id = 0;
376 // Resize HDR supported map to total number of displays
377 is_hdr_display_.resize(1);
378
379 if (!async_powermode_) {
380 return;
381 }
382
383 DLOGI("Display Pairs: map.client_id: %d, start_index: %d", INT32(map_info_primary_.client_id),
384 HWCCallbacks::kNumRealDisplays);
385 map_hwc_display_.insert(std::make_pair(map_info_primary_.client_id,
386 HWCCallbacks::kNumRealDisplays));
387 }
388
GetDisplayIndex(int dpy)389 int HWCSession::GetDisplayIndex(int dpy) {
390 DisplayMapInfo *map_info = nullptr;
391 switch (dpy) {
392 case qdutils::DISPLAY_PRIMARY:
393 map_info = &map_info_primary_;
394 break;
395 case qdutils::DISPLAY_EXTERNAL:
396 map_info = map_info_pluggable_.size() ? &map_info_pluggable_[0] : nullptr;
397 break;
398 case qdutils::DISPLAY_EXTERNAL_2:
399 map_info = (map_info_pluggable_.size() > 1) ? &map_info_pluggable_[1] : nullptr;
400 break;
401 case qdutils::DISPLAY_VIRTUAL:
402 map_info = map_info_virtual_.size() ? &map_info_virtual_[0] : nullptr;
403 break;
404 case qdutils::DISPLAY_BUILTIN_2:
405 map_info = map_info_builtin_.size() ? &map_info_builtin_[0] : nullptr;
406 break;
407 default:
408 DLOGW("Unknown display %d.", dpy);
409 break;
410 }
411
412 if (!map_info) {
413 DLOGE("Display index not found for display %d.", dpy);
414 return -1;
415 }
416
417 return INT(map_info->client_id);
418 }
419
GetCapabilities(uint32_t * outCount,int32_t * outCapabilities)420 void HWCSession::GetCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
421 if (!outCount) {
422 return;
423 }
424
425 int value = 0;
426 bool disable_skip_validate = false;
427 if (Debug::Get()->GetProperty(DISABLE_SKIP_VALIDATE_PROP, &value) == kErrorNone) {
428 disable_skip_validate = (value == 1);
429 }
430 uint32_t count = 1 + (disable_skip_validate ? 0 : 1);
431
432 if (outCapabilities != nullptr && (*outCount >= count)) {
433 outCapabilities[0] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
434 if (!disable_skip_validate) {
435 outCapabilities[1] = HWC2_CAPABILITY_SKIP_VALIDATE;
436 }
437 }
438 *outCount = count;
439 }
440
441 template <typename PFN, typename T>
AsFP(T function)442 static hwc2_function_pointer_t AsFP(T function) {
443 static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
444 return reinterpret_cast<hwc2_function_pointer_t>(function);
445 }
446
447 // HWC2 functions returned in GetFunction
448 // Defined in the same order as in the HWC2 header
449
AcceptDisplayChanges(hwc2_display_t display)450 int32_t HWCSession::AcceptDisplayChanges(hwc2_display_t display) {
451 return CallDisplayFunction(display, &HWCDisplay::AcceptDisplayChanges);
452 }
453
CreateLayer(hwc2_display_t display,hwc2_layer_t * out_layer_id)454 int32_t HWCSession::CreateLayer(hwc2_display_t display,
455 hwc2_layer_t *out_layer_id) {
456 if (!out_layer_id) {
457 return HWC2_ERROR_BAD_PARAMETER;
458 }
459
460 return CallDisplayFunction(display, &HWCDisplay::CreateLayer, out_layer_id);
461 }
462
CreateVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)463 int32_t HWCSession::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t *format,
464 hwc2_display_t *out_display_id) {
465 // TODO(user): Handle concurrency with HDMI
466
467 if (!out_display_id || !width || !height || !format) {
468 return HWC2_ERROR_BAD_PARAMETER;
469 }
470
471 if (null_display_mode_) {
472 return 0;
473 }
474
475 if (async_vds_creation_ && virtual_id_ != HWCCallbacks::kNumDisplays) {
476 *out_display_id = virtual_id_;
477 return HWC2_ERROR_NONE;
478 }
479
480 auto status = CreateVirtualDisplayObj(width, height, format, out_display_id);
481 if (status == HWC2::Error::None) {
482 DLOGI("Created virtual display id:%" PRIu64 ", res: %dx%d", *out_display_id, width, height);
483 } else {
484 DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
485 }
486 return INT32(status);
487 }
488
DestroyLayer(hwc2_display_t display,hwc2_layer_t layer)489 int32_t HWCSession::DestroyLayer(hwc2_display_t display, hwc2_layer_t layer) {
490 return CallDisplayFunction(display, &HWCDisplay::DestroyLayer, layer);
491 }
492
DestroyVirtualDisplay(hwc2_display_t display)493 int32_t HWCSession::DestroyVirtualDisplay(hwc2_display_t display) {
494 if (display >= HWCCallbacks::kNumDisplays) {
495 return HWC2_ERROR_BAD_DISPLAY;
496 }
497
498 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
499
500 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
501 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
502 std::bitset<kSecureMax> secure_sessions = 0;
503 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
504 if (secure_sessions.any()) {
505 DLOGW("Secure session is active, defer destruction of virtual display id:%" PRIu64, display);
506 destroy_virtual_disp_pending_ = true;
507 return HWC2_ERROR_NONE;
508 }
509 }
510
511 for (auto &map_info : map_info_virtual_) {
512 if (map_info.client_id == display) {
513 DLOGI("Destroying virtual display id:%" PRIu64, display);
514 DestroyDisplay(&map_info);
515 break;
516 }
517 }
518 virtual_id_ = HWCCallbacks::kNumDisplays;
519
520 return HWC2_ERROR_NONE;
521 }
522
GetVirtualDisplayId()523 int32_t HWCSession::GetVirtualDisplayId() {
524 HWDisplaysInfo hw_displays_info = {};
525 core_intf_->GetDisplaysStatus(&hw_displays_info);
526 for (auto &iter : hw_displays_info) {
527 auto &info = iter.second;
528 if (info.display_type != kVirtual) {
529 continue;
530 }
531
532 return info.display_id;
533 }
534
535 return -1;
536 }
537
Dump(uint32_t * out_size,char * out_buffer)538 void HWCSession::Dump(uint32_t *out_size, char *out_buffer) {
539 if (!out_size) {
540 return;
541 }
542
543 const size_t max_dump_size = 16384; // 16 kB
544
545 if (out_buffer == nullptr) {
546 *out_size = max_dump_size;
547 } else {
548 std::ostringstream os;
549 for (int id = 0; id < HWCCallbacks::kNumRealDisplays; id++) {
550 SCOPE_LOCK(locker_[id]);
551 if (hwc_display_[id]) {
552 hwc_display_[id]->Dump(&os);
553 }
554 }
555 Fence::Dump(&os);
556
557 std::string s = os.str();
558 auto copied = s.copy(out_buffer, std::min(s.size(), max_dump_size), 0);
559 *out_size = UINT32(copied);
560 }
561 }
562
GetMaxVirtualDisplayCount()563 uint32_t HWCSession::GetMaxVirtualDisplayCount() {
564 return map_info_virtual_.size();
565 }
566
GetActiveConfig(hwc2_display_t display,hwc2_config_t * out_config)567 int32_t HWCSession::GetActiveConfig(hwc2_display_t display, hwc2_config_t *out_config) {
568 return CallDisplayFunction(display, &HWCDisplay::GetActiveConfig, out_config);
569 }
570
GetChangedCompositionTypes(hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_types)571 int32_t HWCSession::GetChangedCompositionTypes(hwc2_display_t display, uint32_t *out_num_elements,
572 hwc2_layer_t *out_layers, int32_t *out_types) {
573 // null_ptr check only for out_num_elements, as out_layers and out_types can be null.
574 if (!out_num_elements) {
575 return HWC2_ERROR_BAD_PARAMETER;
576 }
577 return CallDisplayFunction(display, &HWCDisplay::GetChangedCompositionTypes, out_num_elements,
578 out_layers, out_types);
579 }
580
GetClientTargetSupport(hwc2_display_t display,uint32_t width,uint32_t height,int32_t format,int32_t dataspace)581 int32_t HWCSession::GetClientTargetSupport(hwc2_display_t display, uint32_t width, uint32_t height,
582 int32_t format, int32_t dataspace) {
583 return CallDisplayFunction(display, &HWCDisplay::GetClientTargetSupport, width, height, format,
584 dataspace);
585 }
586
GetColorModes(hwc2_display_t display,uint32_t * out_num_modes,int32_t * int_out_modes)587 int32_t HWCSession::GetColorModes(hwc2_display_t display, uint32_t *out_num_modes,
588 int32_t /*ColorMode*/ *int_out_modes) {
589 auto out_modes = reinterpret_cast<ColorMode *>(int_out_modes);
590 if (out_num_modes == nullptr) {
591 return HWC2_ERROR_BAD_PARAMETER;
592 }
593 return CallDisplayFunction(display, &HWCDisplay::GetColorModes, out_num_modes, out_modes);
594 }
595
GetRenderIntents(hwc2_display_t display,int32_t int_mode,uint32_t * out_num_intents,int32_t * int_out_intents)596 int32_t HWCSession::GetRenderIntents(hwc2_display_t display, int32_t /*ColorMode*/ int_mode,
597 uint32_t *out_num_intents,
598 int32_t /*RenderIntent*/ *int_out_intents) {
599 auto mode = static_cast<ColorMode>(int_mode);
600 auto out_intents = reinterpret_cast<RenderIntent *>(int_out_intents);
601 if (out_num_intents == nullptr) {
602 return HWC2_ERROR_BAD_PARAMETER;
603 }
604
605 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
606 DLOGE("Invalid ColorMode: %d", mode);
607 return HWC2_ERROR_BAD_PARAMETER;
608 }
609 return CallDisplayFunction(display, &HWCDisplay::GetRenderIntents, mode, out_num_intents,
610 out_intents);
611 }
612
GetDataspaceSaturationMatrix(int32_t int_dataspace,float * out_matrix)613 int32_t HWCSession::GetDataspaceSaturationMatrix(int32_t /*Dataspace*/ int_dataspace,
614 float *out_matrix) {
615 auto dataspace = static_cast<Dataspace>(int_dataspace);
616 if (out_matrix == nullptr || dataspace != Dataspace::SRGB_LINEAR) {
617 return HWC2_ERROR_BAD_PARAMETER;
618 }
619 // We only have the matrix for sRGB
620 float saturation_matrix[kDataspaceSaturationMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
621 0.0, 1.0, 0.0, 0.0, \
622 0.0, 0.0, 1.0, 0.0, \
623 0.0, 0.0, 0.0, 1.0 };
624
625 for (int32_t i = 0; i < kDataspaceSaturationMatrixCount; i += 4) {
626 DLOGD("%f %f %f %f", saturation_matrix[i], saturation_matrix[i + 1], saturation_matrix[i + 2],
627 saturation_matrix[i + 3]);
628 }
629 for (uint32_t i = 0; i < kDataspaceSaturationMatrixCount; i++) {
630 out_matrix[i] = saturation_matrix[i];
631 }
632 return HWC2_ERROR_NONE;
633 }
634
GetPerFrameMetadataKeys(hwc2_display_t display,uint32_t * out_num_keys,int32_t * int_out_keys)635 int32_t HWCSession::GetPerFrameMetadataKeys(hwc2_display_t display, uint32_t *out_num_keys,
636 int32_t *int_out_keys) {
637 auto out_keys = reinterpret_cast<PerFrameMetadataKey *>(int_out_keys);
638 return CallDisplayFunction(display, &HWCDisplay::GetPerFrameMetadataKeys, out_num_keys,
639 out_keys);
640 }
641
SetLayerPerFrameMetadata(hwc2_display_t display,hwc2_layer_t layer,uint32_t num_elements,const int32_t * int_keys,const float * metadata)642 int32_t HWCSession::SetLayerPerFrameMetadata(hwc2_display_t display, hwc2_layer_t layer,
643 uint32_t num_elements, const int32_t *int_keys,
644 const float *metadata) {
645 auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
646 return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadata, num_elements,
647 keys, metadata);
648 }
649
SetLayerPerFrameMetadataBlobs(hwc2_display_t display,hwc2_layer_t layer,uint32_t num_elements,const int32_t * int_keys,const uint32_t * sizes,const uint8_t * metadata)650 int32_t HWCSession:: SetLayerPerFrameMetadataBlobs(hwc2_display_t display,
651 hwc2_layer_t layer, uint32_t num_elements,
652 const int32_t *int_keys, const uint32_t *sizes,
653 const uint8_t *metadata) {
654 auto keys = reinterpret_cast<const PerFrameMetadataKey *>(int_keys);
655 return CallLayerFunction(display, layer, &HWCLayer::SetLayerPerFrameMetadataBlobs,
656 num_elements, keys, sizes, metadata);
657 }
658
SetDisplayedContentSamplingEnabled(hwc2_display_t display,int32_t enabled,uint8_t component_mask,uint64_t max_frames)659 int32_t HWCSession::SetDisplayedContentSamplingEnabled(hwc2_display_t display, int32_t enabled,
660 uint8_t component_mask,
661 uint64_t max_frames) {
662 static constexpr int32_t validComponentMask = HWC2_FORMAT_COMPONENT_0 | HWC2_FORMAT_COMPONENT_1 |
663 HWC2_FORMAT_COMPONENT_2 | HWC2_FORMAT_COMPONENT_3;
664 if (component_mask & ~validComponentMask)
665 return HWC2_ERROR_BAD_PARAMETER;
666 return CallDisplayFunction(display, &HWCDisplay::SetDisplayedContentSamplingEnabled, enabled,
667 component_mask, max_frames);
668 }
669
GetDisplayedContentSamplingAttributes(hwc2_display_t display,int32_t * format,int32_t * dataspace,uint8_t * supported_components)670 int32_t HWCSession::GetDisplayedContentSamplingAttributes(hwc2_display_t display, int32_t *format,
671 int32_t *dataspace,
672 uint8_t *supported_components) {
673 return CallDisplayFunction(display, &HWCDisplay::GetDisplayedContentSamplingAttributes, format,
674 dataspace, supported_components);
675 }
676
GetDisplayedContentSample(hwc2_display_t display,uint64_t max_frames,uint64_t timestamp,uint64_t * numFrames,int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],uint64_t * samples[NUM_HISTOGRAM_COLOR_COMPONENTS])677 int32_t HWCSession::GetDisplayedContentSample(hwc2_display_t display, uint64_t max_frames,
678 uint64_t timestamp, uint64_t *numFrames,
679 int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
680 uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
681 return CallDisplayFunction(display, &HWCDisplay::GetDisplayedContentSample, max_frames, timestamp,
682 numFrames, samples_size, samples);
683 }
684
GetDisplayAttribute(hwc2_display_t display,hwc2_config_t config,HwcAttribute attribute,int32_t * out_value)685 int32_t HWCSession::GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
686 HwcAttribute attribute, int32_t *out_value) {
687 if (out_value == nullptr) {
688 return HWC2_ERROR_BAD_PARAMETER;
689 }
690 return CallDisplayFunction(display, &HWCDisplay::GetDisplayAttribute, config, attribute,
691 out_value);
692 }
693
GetDisplayConfigs(hwc2_display_t display,uint32_t * out_num_configs,hwc2_config_t * out_configs)694 int32_t HWCSession::GetDisplayConfigs(hwc2_display_t display, uint32_t *out_num_configs,
695 hwc2_config_t *out_configs) {
696 return CallDisplayFunction(display, &HWCDisplay::GetDisplayConfigs, out_num_configs,
697 out_configs);
698 }
699
GetDisplayName(hwc2_display_t display,uint32_t * out_size,char * out_name)700 int32_t HWCSession::GetDisplayName(hwc2_display_t display, uint32_t *out_size, char *out_name) {
701 return CallDisplayFunction(display, &HWCDisplay::GetDisplayName, out_size, out_name);
702 }
703
GetDisplayRequests(hwc2_display_t display,int32_t * out_display_requests,uint32_t * out_num_elements,hwc2_layer_t * out_layers,int32_t * out_layer_requests)704 int32_t HWCSession::GetDisplayRequests(hwc2_display_t display, int32_t *out_display_requests,
705 uint32_t *out_num_elements, hwc2_layer_t *out_layers,
706 int32_t *out_layer_requests) {
707 return CallDisplayFunction(display, &HWCDisplay::GetDisplayRequests, out_display_requests,
708 out_num_elements, out_layers, out_layer_requests);
709 }
710
GetDisplayType(hwc2_display_t display,int32_t * out_type)711 int32_t HWCSession::GetDisplayType(hwc2_display_t display, int32_t *out_type) {
712 return CallDisplayFunction(display, &HWCDisplay::GetDisplayType, out_type);
713 }
714
715
GetHdrCapabilities(hwc2_display_t display,uint32_t * out_num_types,int32_t * out_types,float * out_max_luminance,float * out_max_average_luminance,float * out_min_luminance)716 int32_t HWCSession::GetHdrCapabilities(hwc2_display_t display, uint32_t* out_num_types,
717 int32_t* out_types, float* out_max_luminance,
718 float* out_max_average_luminance,
719 float* out_min_luminance) {
720 return CallDisplayFunction(display, &HWCDisplay::GetHdrCapabilities, out_num_types, out_types,
721 out_max_luminance, out_max_average_luminance, out_min_luminance);
722 }
723
724
GetReleaseFences(hwc2_display_t display,uint32_t * out_num_elements,hwc2_layer_t * out_layers,std::vector<shared_ptr<Fence>> * out_fences)725 int32_t HWCSession::GetReleaseFences(hwc2_display_t display, uint32_t *out_num_elements,
726 hwc2_layer_t *out_layers,
727 std::vector<shared_ptr<Fence>> *out_fences) {
728 return CallDisplayFunction(display, &HWCDisplay::GetReleaseFences, out_num_elements, out_layers,
729 out_fences);
730 }
731
PerformQsyncCallback(hwc2_display_t display)732 void HWCSession::PerformQsyncCallback(hwc2_display_t display) {
733 std::shared_ptr<DisplayConfig::ConfigCallback> callback = qsync_callback_.lock();
734 if (!callback) {
735 return;
736 }
737
738 bool qsync_enabled = 0;
739 int32_t refresh_rate = 0, qsync_refresh_rate = 0;
740 if (hwc_display_[display]->IsQsyncCallbackNeeded(&qsync_enabled,
741 &refresh_rate, &qsync_refresh_rate)) {
742 callback->NotifyQsyncChange(qsync_enabled, refresh_rate, qsync_refresh_rate);
743 }
744 }
745
PerformIdleStatusCallback(hwc2_display_t display)746 void HWCSession::PerformIdleStatusCallback(hwc2_display_t display) {
747 std::shared_ptr<DisplayConfig::ConfigCallback> callback = idle_callback_.lock();
748 if (!callback) {
749 return;
750 }
751
752 if (hwc_display_[display]->IsDisplayIdle()) {
753 DTRACE_SCOPED();
754 callback->NotifyIdleStatus(true);
755 }
756 }
757
PresentDisplay(hwc2_display_t display,shared_ptr<Fence> * out_retire_fence)758 int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *out_retire_fence) {
759 auto status = HWC2::Error::BadDisplay;
760 DTRACE_SCOPED();
761
762 SCOPE_LOCK(system_locker_);
763 if (display >= HWCCallbacks::kNumDisplays) {
764 DLOGW("Invalid Display : display = %" PRIu64, display);
765 return HWC2_ERROR_BAD_DISPLAY;
766 }
767
768 HandleSecureSession();
769
770
771 hwc2_display_t target_display = display;
772
773 {
774 SCOPE_LOCK(power_state_[display]);
775 if (power_state_transition_[display]) {
776 // Route all interactions with client to dummy display.
777 target_display = map_hwc_display_.find(display)->second;
778 }
779 }
780
781 {
782 SEQUENCE_EXIT_SCOPE_LOCK(locker_[target_display]);
783 if (!hwc_display_[target_display]) {
784 DLOGW("Removed Display : display = %" PRIu64, target_display);
785 return HWC2_ERROR_BAD_DISPLAY;
786 }
787
788 if (out_retire_fence == nullptr) {
789 return HWC2_ERROR_BAD_PARAMETER;
790 }
791
792 if (pending_power_mode_[display]) {
793 status = HWC2::Error::None;
794 } else {
795 hwc_display_[target_display]->ProcessActiveConfigChange();
796 status = PresentDisplayInternal(target_display);
797 if (status == HWC2::Error::None) {
798 // Check if hwc's refresh trigger is getting exercised.
799 if (callbacks_.NeedsRefresh(display)) {
800 hwc_display_[target_display]->SetPendingRefresh();
801 callbacks_.ResetRefresh(display);
802 }
803 status = hwc_display_[target_display]->Present(out_retire_fence);
804 if (status == HWC2::Error::None) {
805 PerformQsyncCallback(target_display);
806 PerformIdleStatusCallback(target_display);
807 }
808 }
809 }
810 }
811
812 if (status != HWC2::Error::None && status != HWC2::Error::NotValidated) {
813 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[target_display]);
814 }
815
816 HandlePendingPowerMode(display, *out_retire_fence);
817 HandlePendingHotplug(display, *out_retire_fence);
818 HandlePendingRefresh();
819 if (status != HWC2::Error::NotValidated) {
820 cwb_.PresentDisplayDone(display);
821 }
822 display_ready_.set(UINT32(display));
823 {
824 std::unique_lock<std::mutex> caller_lock(hotplug_mutex_);
825 hotplug_cv_.notify_one();
826 }
827
828 return INT32(status);
829 }
830
HandlePendingRefresh()831 void HWCSession::HandlePendingRefresh() {
832 if (pending_refresh_.none()) {
833 return;
834 }
835
836 for (size_t i = 0; i < pending_refresh_.size(); i++) {
837 if (pending_refresh_.test(i)) {
838 callbacks_.Refresh(i);
839 break;
840 }
841 }
842
843 pending_refresh_.reset();
844 }
845
RegisterCallback(int32_t descriptor,hwc2_callback_data_t callback_data,hwc2_function_pointer_t pointer)846 void HWCSession::RegisterCallback(int32_t descriptor, hwc2_callback_data_t callback_data,
847 hwc2_function_pointer_t pointer) {
848 auto desc = static_cast<HWC2::Callback>(descriptor);
849
850 // Detect if client died and now is back
851 bool already_connected = false;
852 vector<hwc2_display_t> pending_hotplugs;
853 if (descriptor == HWC2_CALLBACK_HOTPLUG && pointer) {
854 already_connected = callbacks_.IsClientConnected();
855 if (already_connected) {
856 for (auto& map_info : map_info_builtin_) {
857 SCOPE_LOCK(locker_[map_info.client_id]);
858 if (hwc_display_[map_info.client_id]) {
859 pending_hotplugs.push_back(static_cast<hwc2_display_t>(map_info.client_id));
860 }
861 }
862 for (auto& map_info : map_info_pluggable_) {
863 SCOPE_LOCK(locker_[map_info.client_id]);
864 if (hwc_display_[map_info.client_id]) {
865 pending_hotplugs.push_back(static_cast<hwc2_display_t>(map_info.client_id));
866 }
867 }
868 }
869 }
870
871 auto error = callbacks_.Register(desc, callback_data, pointer);
872 if (error != HWC2::Error::None) {
873 return;
874 }
875
876 DLOGI("%s callback: %s", pointer ? "Registering" : "Deregistering", to_string(desc).c_str());
877 if (descriptor == HWC2_CALLBACK_HOTPLUG && pointer) {
878 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
879 DLOGI("Hotplugging primary...");
880 callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
881 }
882 // Create displays since they should now have their final display indices set.
883 DLOGI("Handling built-in displays...");
884 if (HandleBuiltInDisplays()) {
885 DLOGW("Failed handling built-in displays.");
886 }
887 DLOGI("Handling pluggable displays...");
888 int32_t err = HandlePluggableDisplays(false);
889 if (err) {
890 DLOGW("All displays could not be created. Error %d '%s'. Hotplug handling %s.", err,
891 strerror(abs(err)), pending_hotplug_event_ == kHotPlugEvent ? "deferred" :
892 "dropped");
893 }
894
895 // If previously registered, call hotplug for all connected displays to refresh
896 if (already_connected) {
897 std::vector<hwc2_display_t> updated_pending_hotplugs;
898 for (auto client_id : pending_hotplugs) {
899 SCOPE_LOCK(locker_[client_id]);
900 // check if the display is unregistered
901 if (hwc_display_[client_id]) {
902 updated_pending_hotplugs.push_back(client_id);
903 }
904 }
905 for (auto client_id : updated_pending_hotplugs) {
906 DLOGI("Re-hotplug display connected: client id = %d", UINT32(client_id));
907 callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
908 }
909 }
910 }
911
912 if (descriptor == HWC2_CALLBACK_HOTPLUG) {
913 client_connected_ = !!pointer;
914 // Notfify all displays.
915 NotifyClientStatus(client_connected_);
916 }
917 need_invalidate_ = false;
918 }
919
SetActiveConfig(hwc2_display_t display,hwc2_config_t config)920 int32_t HWCSession::SetActiveConfig(hwc2_display_t display, hwc2_config_t config) {
921 return CallDisplayFunction(display, &HWCDisplay::SetActiveConfig, config);
922 }
923
SetClientTarget(hwc2_display_t display,buffer_handle_t target,const shared_ptr<Fence> acquire_fence,int32_t dataspace,hwc_region_t damage)924 int32_t HWCSession::SetClientTarget(hwc2_display_t display, buffer_handle_t target,
925 const shared_ptr<Fence> acquire_fence, int32_t dataspace,
926 hwc_region_t damage) {
927 return CallDisplayFunction(display, &HWCDisplay::SetClientTarget, target, acquire_fence,
928 dataspace, damage);
929 }
930
SetColorMode(hwc2_display_t display,int32_t int_mode)931 int32_t HWCSession::SetColorMode(hwc2_display_t display, int32_t /*ColorMode*/ int_mode) {
932 auto mode = static_cast<ColorMode>(int_mode);
933 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
934 return HWC2_ERROR_BAD_PARAMETER;
935 }
936 return CallDisplayFunction(display, &HWCDisplay::SetColorMode, mode);
937 }
938
SetColorModeWithRenderIntent(hwc2_display_t display,int32_t int_mode,int32_t int_render_intent)939 int32_t HWCSession::SetColorModeWithRenderIntent(hwc2_display_t display,
940 int32_t /*ColorMode*/ int_mode,
941 int32_t /*RenderIntent*/ int_render_intent) {
942 auto mode = static_cast<ColorMode>(int_mode);
943 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
944 return HWC2_ERROR_BAD_PARAMETER;
945 }
946
947 if ((int_render_intent < 0) || (int_render_intent > MAX_EXTENDED_RENDER_INTENT)) {
948 DLOGE("Invalid RenderIntent: %d", int_render_intent);
949 return HWC2_ERROR_BAD_PARAMETER;
950 }
951
952 auto render_intent = static_cast<RenderIntent>(int_render_intent);
953 return CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode,
954 render_intent);
955 }
956
SetColorTransform(hwc2_display_t display,const float * matrix,int32_t hint)957 int32_t HWCSession::SetColorTransform(hwc2_display_t display, const float *matrix,
958 int32_t /*android_color_transform_t*/ hint) {
959 if (!matrix || hint < HAL_COLOR_TRANSFORM_IDENTITY ||
960 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA) {
961 return HWC2_ERROR_BAD_PARAMETER;
962 }
963 android_color_transform_t transform_hint = static_cast<android_color_transform_t>(hint);
964 return CallDisplayFunction(display, &HWCDisplay::SetColorTransform, matrix, transform_hint);
965 }
966
SetCursorPosition(hwc2_display_t display,hwc2_layer_t layer,int32_t x,int32_t y)967 int32_t HWCSession::SetCursorPosition(hwc2_display_t display, hwc2_layer_t layer, int32_t x,
968 int32_t y) {
969 auto status = INT32(HWC2::Error::None);
970 status = CallDisplayFunction(display, &HWCDisplay::SetCursorPosition, layer, x, y);
971 if (status == INT32(HWC2::Error::None)) {
972 // Update cursor position
973 CallLayerFunction(display, layer, &HWCLayer::SetCursorPosition, x, y);
974 }
975 return status;
976 }
977
SetLayerBlendMode(hwc2_display_t display,hwc2_layer_t layer,int32_t int_mode)978 int32_t HWCSession::SetLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
979 int32_t int_mode) {
980 if (int_mode < HWC2_BLEND_MODE_INVALID || int_mode > HWC2_BLEND_MODE_COVERAGE) {
981 return HWC2_ERROR_BAD_PARAMETER;
982 }
983 auto mode = static_cast<HWC2::BlendMode>(int_mode);
984 return CallLayerFunction(display, layer, &HWCLayer::SetLayerBlendMode, mode);
985 }
986
SetLayerBuffer(hwc2_display_t display,hwc2_layer_t layer,buffer_handle_t buffer,const shared_ptr<Fence> & acquire_fence)987 int32_t HWCSession::SetLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
988 buffer_handle_t buffer,
989 const shared_ptr<Fence> &acquire_fence) {
990 return CallLayerFunction(display, layer, &HWCLayer::SetLayerBuffer, buffer, acquire_fence);
991 }
992
SetLayerColor(hwc2_display_t display,hwc2_layer_t layer,hwc_color_t color)993 int32_t HWCSession::SetLayerColor(hwc2_display_t display, hwc2_layer_t layer, hwc_color_t color) {
994 return CallLayerFunction(display, layer, &HWCLayer::SetLayerColor, color);
995 }
996
SetLayerCompositionType(hwc2_display_t display,hwc2_layer_t layer,int32_t int_type)997 int32_t HWCSession::SetLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
998 int32_t int_type) {
999 auto type = static_cast<HWC2::Composition>(int_type);
1000 return CallLayerFunction(display, layer, &HWCLayer::SetLayerCompositionType, type);
1001 }
1002
SetLayerDataspace(hwc2_display_t display,hwc2_layer_t layer,int32_t dataspace)1003 int32_t HWCSession::SetLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
1004 int32_t dataspace) {
1005 return CallLayerFunction(display, layer, &HWCLayer::SetLayerDataspace, dataspace);
1006 }
1007
SetLayerDisplayFrame(hwc2_display_t display,hwc2_layer_t layer,hwc_rect_t frame)1008 int32_t HWCSession::SetLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
1009 hwc_rect_t frame) {
1010 return CallLayerFunction(display, layer, &HWCLayer::SetLayerDisplayFrame, frame);
1011 }
1012
SetLayerPlaneAlpha(hwc2_display_t display,hwc2_layer_t layer,float alpha)1013 int32_t HWCSession::SetLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer, float alpha) {
1014 return CallLayerFunction(display, layer, &HWCLayer::SetLayerPlaneAlpha, alpha);
1015 }
1016
SetLayerSourceCrop(hwc2_display_t display,hwc2_layer_t layer,hwc_frect_t crop)1017 int32_t HWCSession::SetLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
1018 hwc_frect_t crop) {
1019 return HWCSession::CallLayerFunction(display, layer, &HWCLayer::SetLayerSourceCrop, crop);
1020 }
1021
SetLayerSurfaceDamage(hwc2_display_t display,hwc2_layer_t layer,hwc_region_t damage)1022 int32_t HWCSession::SetLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
1023 hwc_region_t damage) {
1024 return CallLayerFunction(display, layer, &HWCLayer::SetLayerSurfaceDamage, damage);
1025 }
1026
SetLayerTransform(hwc2_display_t display,hwc2_layer_t layer,int32_t int_transform)1027 int32_t HWCSession::SetLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
1028 int32_t int_transform) {
1029 auto transform = static_cast<HWC2::Transform>(int_transform);
1030 return CallLayerFunction(display, layer, &HWCLayer::SetLayerTransform, transform);
1031 }
1032
SetLayerVisibleRegion(hwc2_display_t display,hwc2_layer_t layer,hwc_region_t visible)1033 int32_t HWCSession::SetLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
1034 hwc_region_t visible) {
1035 return CallLayerFunction(display, layer, &HWCLayer::SetLayerVisibleRegion, visible);
1036 }
1037
SetLayerZOrder(hwc2_display_t display,hwc2_layer_t layer,uint32_t z)1038 int32_t HWCSession::SetLayerZOrder(hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
1039 return CallDisplayFunction(display, &HWCDisplay::SetLayerZOrder, layer, z);
1040 }
1041
SetLayerType(hwc2_display_t display,hwc2_layer_t layer,IQtiComposerClient::LayerType type)1042 int32_t HWCSession::SetLayerType(hwc2_display_t display, hwc2_layer_t layer,
1043 IQtiComposerClient::LayerType type) {
1044 return CallDisplayFunction(display, &HWCDisplay::SetLayerType, layer, type);
1045 }
1046
SetLayerColorTransform(hwc2_display_t display,hwc2_layer_t layer,const float * matrix)1047 int32_t HWCSession::SetLayerColorTransform(hwc2_display_t display, hwc2_layer_t layer,
1048 const float *matrix) {
1049 return CallLayerFunction(display, layer, &HWCLayer::SetLayerColorTransform, matrix);
1050 }
1051
SetDisplayElapseTime(hwc2_display_t display,uint64_t time)1052 int32_t HWCSession::SetDisplayElapseTime(hwc2_display_t display, uint64_t time) {
1053 return CallDisplayFunction(display, &HWCDisplay::SetDisplayElapseTime, time);
1054 }
1055
SetOutputBuffer(hwc2_display_t display,buffer_handle_t buffer,const shared_ptr<Fence> & release_fence)1056 int32_t HWCSession::SetOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
1057 const shared_ptr<Fence> &release_fence) {
1058 if (INT32(display) != GetDisplayIndex(qdutils::DISPLAY_VIRTUAL)) {
1059 return HWC2_ERROR_UNSUPPORTED;
1060 }
1061
1062 SCOPE_LOCK(locker_[display]);
1063 if (hwc_display_[display]) {
1064 auto vds = reinterpret_cast<HWCDisplayVirtual *>(hwc_display_[display]);
1065 auto status = vds->SetOutputBuffer(buffer, release_fence);
1066 return INT32(status);
1067 } else {
1068 return HWC2_ERROR_BAD_DISPLAY;
1069 }
1070 }
1071
SetPowerMode(hwc2_display_t display,int32_t int_mode)1072 int32_t HWCSession::SetPowerMode(hwc2_display_t display, int32_t int_mode) {
1073 if (display >= HWCCallbacks::kNumDisplays) {
1074 return HWC2_ERROR_BAD_DISPLAY;
1075 }
1076
1077 // validate device and also avoid undefined behavior in cast to HWC2::PowerMode
1078 if (int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
1079 return HWC2_ERROR_BAD_PARAMETER;
1080 }
1081
1082 auto mode = static_cast<HWC2::PowerMode>(int_mode);
1083
1084 // When secure session going on primary, if power request comes on second built-in, cache it and
1085 // process once secure session ends.
1086 // Allow power off transition during secure session.
1087 bool is_builtin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
1088 bool is_power_off = (hwc_display_[display]->GetCurrentPowerMode() == HWC2::PowerMode::Off);
1089 if (secure_session_active_ && is_builtin && is_power_off) {
1090 if (GetActiveBuiltinDisplay() != HWCCallbacks::kNumDisplays) {
1091 DLOGI("Secure session in progress, defer power state change");
1092 hwc_display_[display]->SetPendingPowerMode(mode);
1093 return HWC2_ERROR_NONE;
1094 }
1095 }
1096
1097 if (pending_power_mode_[display]) {
1098 DLOGW("Set power mode is not allowed during secure display session");
1099 return HWC2_ERROR_UNSUPPORTED;
1100 }
1101
1102 // all displays support on/off. Check for doze modes
1103 int support = 0;
1104 auto status = GetDozeSupport(display, &support);
1105 if (status != HWC2_ERROR_NONE) {
1106 DLOGE("Failed to get doze support Error = %d", status);
1107 return INT32(status);
1108 }
1109
1110 if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
1111 return HWC2_ERROR_UNSUPPORTED;
1112 }
1113
1114 // async_powermode supported for power on and off
1115 bool override_mode = async_powermode_ && display_ready_.test(UINT32(display)) &&
1116 async_power_mode_triggered_;
1117 HWC2::PowerMode last_power_mode = hwc_display_[display]->GetCurrentPowerMode();
1118
1119 if (last_power_mode == mode) {
1120 return HWC2_ERROR_NONE;
1121 }
1122
1123 if (!((last_power_mode == HWC2::PowerMode::Off && mode == HWC2::PowerMode::On) ||
1124 (last_power_mode == HWC2::PowerMode::On && mode == HWC2::PowerMode::Off))) {
1125 override_mode = false;
1126 }
1127
1128 if (!override_mode) {
1129 auto error = CallDisplayFunction(display, &HWCDisplay::SetPowerMode, mode,
1130 false /* teardown */);
1131 if (INT32(error) != HWC2_ERROR_NONE) {
1132 return INT32(error);
1133 }
1134 } else {
1135 Locker::ScopeLock lock_disp(locker_[display]);
1136 // Update hwc state for now. Actual poweron will handled through DisplayConfig.
1137 hwc_display_[display]->UpdatePowerMode(mode);
1138 }
1139 // Reset idle pc ref count on suspend, as we enable idle pc during suspend.
1140 if (mode == HWC2::PowerMode::Off) {
1141 idle_pc_ref_cnt_ = 0;
1142 }
1143
1144
1145 UpdateThrottlingRate();
1146
1147 if (mode == HWC2::PowerMode::Doze) {
1148 // Trigger one more refresh for PP features to take effect.
1149 pending_refresh_.set(UINT32(display));
1150 }
1151
1152 return HWC2_ERROR_NONE;
1153 }
1154
SetVsyncEnabled(hwc2_display_t display,int32_t int_enabled)1155 int32_t HWCSession::SetVsyncEnabled(hwc2_display_t display, int32_t int_enabled) {
1156 // avoid undefined behavior in cast to HWC2::Vsync
1157 if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
1158 return HWC2_ERROR_BAD_PARAMETER;
1159 }
1160
1161 auto enabled = static_cast<HWC2::Vsync>(int_enabled);
1162
1163 if (int_enabled == HWC2_VSYNC_ENABLE) {
1164 callbacks_.UpdateVsyncSource(display);
1165 }
1166
1167 return CallDisplayFunction(display, &HWCDisplay::SetVsyncEnabled, enabled);
1168 }
1169
GetDozeSupport(hwc2_display_t display,int32_t * out_support)1170 int32_t HWCSession::GetDozeSupport(hwc2_display_t display, int32_t *out_support) {
1171 if (!out_support) {
1172 return HWC2_ERROR_BAD_PARAMETER;
1173 }
1174
1175 if (display >= HWCCallbacks::kNumDisplays || (hwc_display_[display] == nullptr)) {
1176 // display may come as -1 from VTS test case
1177 DLOGE("Invalid Display %d ", UINT32(display));
1178 return HWC2_ERROR_BAD_DISPLAY;
1179 }
1180
1181 *out_support = 0;
1182
1183 SCOPE_LOCK(locker_[display]);
1184 if (!hwc_display_[display]) {
1185 DLOGE("Display %d is not created yet.", INT32(display));
1186 return HWC2_ERROR_BAD_DISPLAY;
1187 }
1188
1189 if (hwc_display_[display]->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
1190 return HWC2_ERROR_NONE;
1191 }
1192
1193 *out_support = hwc_display_[display]->HasSmartPanelConfig() ? 1 : 0;
1194
1195 return HWC2_ERROR_NONE;
1196 }
1197
isSmartPanelConfig(uint32_t disp_id,uint32_t config_id)1198 bool HWCSession::isSmartPanelConfig(uint32_t disp_id, uint32_t config_id) {
1199 if (disp_id != qdutils::DISPLAY_PRIMARY) {
1200 return false;
1201 }
1202
1203 SCOPE_LOCK(locker_[disp_id]);
1204 if (!hwc_display_[disp_id]) {
1205 DLOGE("Display %d is not created yet.", disp_id);
1206 return false;
1207 }
1208
1209 return hwc_display_[disp_id]->IsSmartPanelConfig(config_id);
1210 }
1211
ValidateDisplay(hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)1212 int32_t HWCSession::ValidateDisplay(hwc2_display_t display, uint32_t *out_num_types,
1213 uint32_t *out_num_requests) {
1214 // out_num_types and out_num_requests will be non-NULL
1215
1216 if (display >= HWCCallbacks::kNumDisplays) {
1217 return HWC2_ERROR_BAD_DISPLAY;
1218 }
1219
1220 hwc2_display_t target_display = display;
1221
1222 {
1223 SCOPE_LOCK(power_state_[display]);
1224 if (power_state_transition_[display]) {
1225 // Route all interactions with client to dummy display.
1226 target_display = map_hwc_display_.find(display)->second;
1227 }
1228 }
1229 DTRACE_SCOPED();
1230 // TODO(user): Handle secure session, handle QDCM solid fill
1231 auto status = HWC2::Error::BadDisplay;
1232 HandleSecureSession();
1233 {
1234 SEQUENCE_ENTRY_SCOPE_LOCK(locker_[target_display]);
1235 if (pending_power_mode_[display]) {
1236 status = HWC2::Error::None;
1237 } else if (hwc_display_[target_display]) {
1238 hwc_display_[target_display]->ProcessActiveConfigChange();
1239 hwc_display_[target_display]->SetFastPathComposition(false);
1240 status = ValidateDisplayInternal(target_display, out_num_types, out_num_requests);
1241 }
1242 }
1243
1244 // Sequence locking currently begins on Validate, so cancel the sequence lock on failures
1245 if (status != HWC2::Error::None && status != HWC2::Error::HasChanges) {
1246 SEQUENCE_CANCEL_SCOPE_LOCK(locker_[target_display]);
1247 }
1248
1249 if (display != target_display) {
1250 // Validate done on a dummy display. Assume present is complete.
1251 SEQUENCE_EXIT_SCOPE_LOCK(locker_[target_display]);
1252 }
1253
1254 return INT32(status);
1255 }
1256
CreateVirtualDisplayObj(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * out_display_id)1257 HWC2::Error HWCSession::CreateVirtualDisplayObj(uint32_t width, uint32_t height, int32_t *format,
1258 hwc2_display_t *out_display_id) {
1259 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
1260 hwc2_display_t client_id = HWCCallbacks::kNumDisplays;
1261 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
1262 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1263 std::bitset<kSecureMax> secure_sessions = 0;
1264 if (hwc_display_[active_builtin_disp_id]) {
1265 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
1266 }
1267 if (secure_sessions.any()) {
1268 DLOGE("Secure session is active, cannot create virtual display.");
1269 return HWC2::Error::Unsupported;
1270 } else if (IsPluggableDisplayConnected()) {
1271 DLOGE("External session is active, cannot create virtual display.");
1272 return HWC2::Error::Unsupported;
1273 }
1274 }
1275
1276 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
1277 DisplayError error = hwc_display_[HWC_DISPLAY_PRIMARY]->TeardownConcurrentWriteback();
1278 if (error) {
1279 return HWC2::Error::NoResources;
1280 }
1281 }
1282
1283 // Lock confined to this scope
1284 int status = -EINVAL;
1285 for (auto &map_info : map_info_virtual_) {
1286 client_id = map_info.client_id;
1287 {
1288 SCOPE_LOCK(locker_[client_id]);
1289 auto &hwc_display = hwc_display_[client_id];
1290 if (hwc_display) {
1291 continue;
1292 }
1293
1294 int32_t display_id = GetVirtualDisplayId();
1295 status = virtual_display_factory_.Create(core_intf_, &buffer_allocator_, &callbacks_,
1296 client_id, display_id, width, height,
1297 format, set_min_lum_, set_max_lum_, &hwc_display);
1298 // TODO(user): validate width and height support
1299 if (status) {
1300 return HWC2::Error::NoResources;
1301 }
1302
1303 {
1304 SCOPE_LOCK(hdr_locker_[client_id]);
1305 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
1306 }
1307
1308 DLOGI("Created virtual display id:%" PRIu64 " with res: %dx%d", client_id, width, height);
1309
1310 *out_display_id = client_id;
1311 map_info.disp_type = kVirtual;
1312 map_info.sdm_id = display_id;
1313 break;
1314 }
1315 }
1316
1317 // Active builtin display needs revalidation
1318 if (!async_vds_creation_ && active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
1319 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
1320 hwc_display_[active_builtin_disp_id]->ResetValidation();
1321 }
1322
1323 return HWC2::Error::None;
1324 }
1325
IsPluggableDisplayConnected()1326 bool HWCSession::IsPluggableDisplayConnected() {
1327 for (auto &map_info : map_info_pluggable_) {
1328 if (hwc_display_[map_info.client_id]) {
1329 return true;
1330 }
1331 }
1332 return false;
1333 }
1334
1335 // Qclient methods
notifyCallback(uint32_t command,const android::Parcel * input_parcel,android::Parcel * output_parcel)1336 android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel,
1337 android::Parcel *output_parcel) {
1338 android::status_t status = -EINVAL;
1339
1340 switch (command) {
1341 case qService::IQService::DYNAMIC_DEBUG:
1342 if (!input_parcel) {
1343 DLOGE("QService command = %d: input_parcel needed.", command);
1344 break;
1345 }
1346 status = 0;
1347 DynamicDebug(input_parcel);
1348 break;
1349
1350 case qService::IQService::SCREEN_REFRESH:
1351 if (!input_parcel) {
1352 DLOGE("QService command = %d: input_parcel needed.", command);
1353 break;
1354 }
1355 status = RefreshScreen(input_parcel);
1356 break;
1357
1358 case qService::IQService::SET_IDLE_TIMEOUT:
1359 if (!input_parcel) {
1360 DLOGE("QService command = %d: input_parcel needed.", command);
1361 break;
1362 }
1363 status = SetIdleTimeout(UINT32(input_parcel->readInt32()));
1364 break;
1365
1366 case qService::IQService::SET_FRAME_DUMP_CONFIG:
1367 if (!input_parcel) {
1368 DLOGE("QService command = %d: input_parcel needed.", command);
1369 break;
1370 }
1371 status = SetFrameDumpConfig(input_parcel);
1372 break;
1373
1374 case qService::IQService::SET_MAX_PIPES_PER_MIXER:
1375 if (!input_parcel) {
1376 DLOGE("QService command = %d: input_parcel needed.", command);
1377 break;
1378 }
1379 status = SetMaxMixerStages(input_parcel);
1380 break;
1381
1382 case qService::IQService::SET_DISPLAY_MODE:
1383 if (!input_parcel) {
1384 DLOGE("QService command = %d: input_parcel needed.", command);
1385 break;
1386 }
1387 status = SetDisplayMode(input_parcel);
1388 break;
1389
1390 case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: {
1391 if (!input_parcel || !output_parcel) {
1392 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1393 break;
1394 }
1395 int disp_id = INT(input_parcel->readInt32());
1396 HWCDisplay::DisplayStatus disp_status =
1397 static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1398 status = SetDisplayStatus(disp_id, disp_status);
1399 output_parcel->writeInt32(status);
1400 }
1401 break;
1402
1403 case qService::IQService::CONFIGURE_DYN_REFRESH_RATE:
1404 if (!input_parcel) {
1405 DLOGE("QService command = %d: input_parcel needed.", command);
1406 break;
1407 }
1408 status = ConfigureRefreshRate(input_parcel);
1409 break;
1410
1411 case qService::IQService::TOGGLE_SCREEN_UPDATES: {
1412 if (!input_parcel || !output_parcel) {
1413 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1414 break;
1415 }
1416 int32_t input = input_parcel->readInt32();
1417 status = ToggleScreenUpdate(input == 1);
1418 output_parcel->writeInt32(status);
1419 }
1420 break;
1421
1422 case qService::IQService::QDCM_SVC_CMDS:
1423 if (!input_parcel || !output_parcel) {
1424 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1425 break;
1426 }
1427 status = QdcmCMDHandler(input_parcel, output_parcel);
1428 break;
1429
1430 case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: {
1431 if (!input_parcel || !output_parcel) {
1432 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1433 break;
1434 }
1435 int disp_id = input_parcel->readInt32();
1436 uint32_t min_enc_level = UINT32(input_parcel->readInt32());
1437 status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level);
1438 output_parcel->writeInt32(status);
1439 }
1440 break;
1441
1442 case qService::IQService::CONTROL_PARTIAL_UPDATE: {
1443 if (!input_parcel || !output_parcel) {
1444 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1445 break;
1446 }
1447 int disp_id = input_parcel->readInt32();
1448 uint32_t enable = UINT32(input_parcel->readInt32());
1449 status = ControlPartialUpdate(disp_id, enable == 1);
1450 output_parcel->writeInt32(status);
1451 }
1452 break;
1453
1454 case qService::IQService::SET_ACTIVE_CONFIG: {
1455 if (!input_parcel) {
1456 DLOGE("QService command = %d: input_parcel needed.", command);
1457 break;
1458 }
1459 uint32_t config = UINT32(input_parcel->readInt32());
1460 int disp_id = input_parcel->readInt32();
1461 status = SetActiveConfigIndex(disp_id, config);
1462 }
1463 break;
1464
1465 case qService::IQService::GET_ACTIVE_CONFIG: {
1466 if (!input_parcel || !output_parcel) {
1467 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1468 break;
1469 }
1470 int disp_id = input_parcel->readInt32();
1471 uint32_t config = 0;
1472 status = GetActiveConfigIndex(disp_id, &config);
1473 output_parcel->writeInt32(INT(config));
1474 }
1475 break;
1476
1477 case qService::IQService::GET_CONFIG_COUNT: {
1478 if (!input_parcel || !output_parcel) {
1479 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1480 break;
1481 }
1482 int disp_id = input_parcel->readInt32();
1483 uint32_t count = 0;
1484 status = GetConfigCount(disp_id, &count);
1485 output_parcel->writeInt32(INT(count));
1486 }
1487 break;
1488
1489 case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG:
1490 if (!input_parcel || !output_parcel) {
1491 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1492 break;
1493 }
1494 status = GetDisplayAttributesForConfig(input_parcel, output_parcel);
1495 break;
1496
1497 case qService::IQService::GET_PANEL_BRIGHTNESS: {
1498 if (!output_parcel) {
1499 DLOGE("QService command = %d: output_parcel needed.", command);
1500 break;
1501 }
1502
1503 uint32_t display = input_parcel->readUint32();
1504 uint32_t max_brightness_level = 0;
1505 status = getDisplayMaxBrightness(display, &max_brightness_level);
1506 if (status || !max_brightness_level) {
1507 output_parcel->writeInt32(max_brightness_level);
1508 DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
1509 break;
1510 }
1511 DLOGV("Panel Max brightness is %u", max_brightness_level);
1512
1513 float brightness_precent = -1.0f;
1514 status = getDisplayBrightness(display, &brightness_precent);
1515 if (brightness_precent == -1.0f) {
1516 output_parcel->writeInt32(0);
1517 } else {
1518 output_parcel->writeInt32(INT32(brightness_precent*(max_brightness_level - 1) + 1));
1519 }
1520 }
1521 break;
1522
1523 case qService::IQService::SET_PANEL_BRIGHTNESS: {
1524 if (!input_parcel || !output_parcel) {
1525 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1526 break;
1527 }
1528
1529 uint32_t max_brightness_level = 0;
1530 uint32_t display = HWC_DISPLAY_PRIMARY;
1531 status = getDisplayMaxBrightness(display, &max_brightness_level);
1532 if (status || max_brightness_level <= 1) {
1533 output_parcel->writeInt32(max_brightness_level);
1534 DLOGE("Failed to get max brightness %u, status %d", max_brightness_level, status);
1535 break;
1536 }
1537 DLOGV("Panel Max brightness is %u", max_brightness_level);
1538
1539 int level = input_parcel->readInt32();
1540 if (level == 0) {
1541 status = SetDisplayBrightness(display, -1.0f);
1542 } else {
1543 status = SetDisplayBrightness(display,
1544 (level - 1)/(static_cast<float>(max_brightness_level - 1)));
1545 }
1546 output_parcel->writeInt32(status);
1547 }
1548 break;
1549
1550 case qService::IQService::GET_DISPLAY_VISIBLE_REGION:
1551 if (!input_parcel || !output_parcel) {
1552 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1553 break;
1554 }
1555 status = GetVisibleDisplayRect(input_parcel, output_parcel);
1556 break;
1557
1558 case qService::IQService::SET_CAMERA_STATUS: {
1559 if (!input_parcel) {
1560 DLOGE("QService command = %d: input_parcel needed.", command);
1561 break;
1562 }
1563 uint32_t camera_status = UINT32(input_parcel->readInt32());
1564 status = SetCameraLaunchStatus(camera_status);
1565 }
1566 break;
1567
1568 case qService::IQService::GET_BW_TRANSACTION_STATUS: {
1569 if (!output_parcel) {
1570 DLOGE("QService command = %d: output_parcel needed.", command);
1571 break;
1572 }
1573 bool state = true;
1574 status = DisplayBWTransactionPending(&state);
1575 output_parcel->writeInt32(state);
1576 }
1577 break;
1578
1579 case qService::IQService::SET_LAYER_MIXER_RESOLUTION:
1580 if (!input_parcel) {
1581 DLOGE("QService command = %d: input_parcel needed.", command);
1582 break;
1583 }
1584 status = SetMixerResolution(input_parcel);
1585 break;
1586
1587 case qService::IQService::SET_COLOR_MODE:
1588 if (!input_parcel) {
1589 DLOGE("QService command = %d: input_parcel needed.", command);
1590 break;
1591 }
1592 status = SetColorModeOverride(input_parcel);
1593 break;
1594
1595 case qService::IQService::SET_COLOR_MODE_WITH_RENDER_INTENT:
1596 if (!input_parcel) {
1597 DLOGE("QService command = %d: input_parcel needed.", command);
1598 break;
1599 }
1600 status = SetColorModeWithRenderIntentOverride(input_parcel);
1601 break;
1602
1603 case qService::IQService::SET_COLOR_MODE_BY_ID:
1604 if (!input_parcel) {
1605 DLOGE("QService command = %d: input_parcel needed.", command);
1606 break;
1607 }
1608 status = SetColorModeById(input_parcel);
1609 break;
1610
1611 case qService::IQService::GET_COMPOSER_STATUS:
1612 if (!output_parcel) {
1613 DLOGE("QService command = %d: output_parcel needed.", command);
1614 break;
1615 }
1616 status = 0;
1617 output_parcel->writeInt32(getComposerStatus());
1618 break;
1619
1620 case qService::IQService::SET_QSYNC_MODE:
1621 if (!input_parcel) {
1622 DLOGE("QService command = %d: input_parcel needed.", command);
1623 break;
1624 }
1625 status = SetQSyncMode(input_parcel);
1626 break;
1627
1628 case qService::IQService::SET_COLOR_SAMPLING_ENABLED:
1629 if (!input_parcel) {
1630 DLOGE("QService command = %d: input_parcel needed.", command);
1631 break;
1632 }
1633 status = setColorSamplingEnabled(input_parcel);
1634 break;
1635
1636 case qService::IQService::SET_IDLE_PC:
1637 if (!input_parcel) {
1638 DLOGE("QService command = %d: input_parcel needed.", command);
1639 break;
1640 }
1641 status = SetIdlePC(input_parcel);
1642 break;
1643
1644 case qService::IQService::SET_DISPLAY_DEVICE_STATUS:
1645 if (!input_parcel) {
1646 DLOGE("QService command = %d: input_parcel needed.", command);
1647 break;
1648 }
1649 status = SetDisplayDeviceStatus(input_parcel);
1650 break;
1651
1652 case qService::IQService::SET_PANEL_GAMMA_TABLE_SOURCE:
1653 if (!input_parcel || !output_parcel) {
1654 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1655 break;
1656 }
1657 status = SetPanelGammaTableSource(input_parcel);
1658 output_parcel->writeInt32(status);
1659 break;
1660
1661 case qService::IQService::SET_DPPS_AD4_ROI_CONFIG:
1662 if (!input_parcel) {
1663 DLOGE("QService command = %d: input_parcel needed.", command);
1664 break;
1665 }
1666 status = SetAd4RoiConfig(input_parcel);
1667 break;
1668
1669 case qService::IQService::SET_DSI_CLK:
1670 if (!input_parcel) {
1671 DLOGE("QService command = %d: input_parcel needed.", command);
1672 break;
1673 }
1674 status = SetDsiClk(input_parcel);
1675 break;
1676
1677 case qService::IQService::GET_DSI_CLK:
1678 if (!input_parcel || !output_parcel) {
1679 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1680 break;
1681 }
1682 status = GetDsiClk(input_parcel, output_parcel);
1683 break;
1684
1685 case qService::IQService::GET_SUPPORTED_DSI_CLK:
1686 if (!input_parcel || !output_parcel) {
1687 DLOGE("QService command = %d: input_parcel and output_parcel needed.", command);
1688 break;
1689 }
1690 status = GetSupportedDsiClk(input_parcel, output_parcel);
1691 break;
1692
1693 case qService::IQService::SET_PANEL_LUMINANCE:
1694 if (!input_parcel) {
1695 DLOGE("QService command = %d: input_parcel needed.", command);
1696 break;
1697 }
1698 status = SetPanelLuminanceAttributes(input_parcel);
1699 break;
1700
1701 case qService::IQService::SET_COLOR_MODE_FROM_CLIENT:
1702 if (!input_parcel) {
1703 DLOGE("QService command = %d: input_parcel needed.", command);
1704 break;
1705 }
1706 status = SetColorModeFromClient(input_parcel);
1707 break;
1708
1709 case qService::IQService::SET_FRAME_TRIGGER_MODE:
1710 if (!input_parcel) {
1711 DLOGE("QService command = %d: input_parcel needed.", command);
1712 break;
1713 }
1714 status = SetFrameTriggerMode(input_parcel);
1715 break;
1716
1717 case qService::IQService::SET_BRIGHTNESS_SCALE:
1718 if (!input_parcel) {
1719 DLOGE("QService command = %d: input_parcel needed.", command);
1720 break;
1721 }
1722 status = SetDisplayBrightnessScale(input_parcel);
1723 break;
1724
1725 case qService::IQService::SET_STAND_BY_MODE:
1726 if (!input_parcel) {
1727 DLOGE("QService command = %d: input_parcel needed.", command);
1728 break;
1729 }
1730 status = SetStandByMode(input_parcel);
1731 break;
1732
1733 default:
1734 DLOGW("QService command = %d is not supported.", command);
1735 break;
1736 }
1737
1738 return status;
1739 }
1740
SetDisplayDeviceStatus(const android::Parcel * input_parcel)1741 android::status_t HWCSession::SetDisplayDeviceStatus(const android::Parcel *input_parcel) {
1742 int dpy = input_parcel->readInt32();
1743 int error = android::BAD_VALUE;
1744 auto disp_status = static_cast<HWCDisplay::DisplayStatus>(input_parcel->readInt32());
1745
1746 int disp_idx = GetDisplayIndex(dpy);
1747 if (disp_idx == -1) {
1748 DLOGE("Invalid display = %d", dpy);
1749 return android::BAD_VALUE;
1750 }
1751
1752 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1753 if (hwc_display_[disp_idx]) {
1754 error = hwc_display_[disp_idx]->SetDisplayStatus(disp_status);
1755 if (error != android::OK)
1756 DLOGW("Set display %d status to %d failed with error %d", dpy, disp_status, error);
1757 } else {
1758 DLOGW("No display %d active", dpy);
1759 }
1760
1761 return error;
1762 }
1763
SetPanelGammaTableSource(const android::Parcel * input_parcel)1764 android::status_t HWCSession::SetPanelGammaTableSource(const android::Parcel *input_parcel) {
1765 int dpy = input_parcel->readInt32();
1766 int error = android::BAD_VALUE;
1767 auto source = static_cast<HWCDisplay::PanelGammaSource>(input_parcel->readInt32());
1768
1769 int disp_idx = GetDisplayIndex(dpy);
1770 if (disp_idx == -1) {
1771 DLOGE("Invalid display = %d", dpy);
1772 return android::BAD_VALUE;
1773 }
1774
1775 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1776 if (hwc_display_[disp_idx]) {
1777 error = hwc_display_[disp_idx]->SetCurrentPanelGammaSource(source);
1778 if (error != android::OK)
1779 DLOGW("Set display %d gamma source to %d failed with error %d", dpy, source, error);
1780 } else {
1781 DLOGW("No display %d active", dpy);
1782 }
1783
1784 return error;
1785 }
1786
getComposerStatus()1787 android::status_t HWCSession::getComposerStatus() {
1788 return is_composer_up_;
1789 }
1790
GetDisplayAttributesForConfig(const android::Parcel * input_parcel,android::Parcel * output_parcel)1791 android::status_t HWCSession::GetDisplayAttributesForConfig(const android::Parcel *input_parcel,
1792 android::Parcel *output_parcel) {
1793 int config = input_parcel->readInt32();
1794 int dpy = input_parcel->readInt32();
1795 int error = android::BAD_VALUE;
1796 DisplayConfigVariableInfo display_attributes;
1797
1798 int disp_idx = GetDisplayIndex(dpy);
1799 if (disp_idx == -1 || config < 0) {
1800 DLOGE("Invalid display = %d, or config = %d", dpy, config);
1801 return android::BAD_VALUE;
1802 }
1803
1804 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1805 if (hwc_display_[disp_idx]) {
1806 error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(config, &display_attributes);
1807 if (error == 0) {
1808 output_parcel->writeInt32(INT(display_attributes.vsync_period_ns));
1809 output_parcel->writeInt32(INT(display_attributes.x_pixels));
1810 output_parcel->writeInt32(INT(display_attributes.y_pixels));
1811 output_parcel->writeFloat(display_attributes.x_dpi);
1812 output_parcel->writeFloat(display_attributes.y_dpi);
1813 output_parcel->writeInt32(0); // Panel type, unsupported.
1814 }
1815 }
1816
1817 return error;
1818 }
1819
setColorSamplingEnabled(const android::Parcel * input_parcel)1820 android::status_t HWCSession::setColorSamplingEnabled(const android::Parcel *input_parcel) {
1821 int dpy = input_parcel->readInt32();
1822 int enabled_cmd = input_parcel->readInt32();
1823 if (dpy < HWC_DISPLAY_PRIMARY || dpy >= HWC_NUM_DISPLAY_TYPES || enabled_cmd < 0 ||
1824 enabled_cmd > 1) {
1825 return android::BAD_VALUE;
1826 }
1827
1828 SEQUENCE_WAIT_SCOPE_LOCK(locker_[dpy]);
1829 if (!hwc_display_[dpy]) {
1830 DLOGW("No display id %i active to enable histogram event", dpy);
1831 return android::BAD_VALUE;
1832 }
1833
1834 auto error = hwc_display_[dpy]->SetDisplayedContentSamplingEnabledVndService(enabled_cmd);
1835 return (error == HWC2::Error::None) ? android::OK : android::BAD_VALUE;
1836 }
1837
ConfigureRefreshRate(const android::Parcel * input_parcel)1838 android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) {
1839 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1840
1841 uint32_t operation = UINT32(input_parcel->readInt32());
1842 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
1843
1844 if (!hwc_display) {
1845 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1846 return -ENODEV;
1847 }
1848
1849 switch (operation) {
1850 case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE:
1851 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
1852
1853 case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE:
1854 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
1855
1856 case qdutils::SET_BINDER_DYN_REFRESH_RATE: {
1857 uint32_t refresh_rate = UINT32(input_parcel->readInt32());
1858 return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
1859 }
1860
1861 default:
1862 DLOGW("Invalid operation %d", operation);
1863 return -EINVAL;
1864 }
1865
1866 return 0;
1867 }
1868
SetDisplayMode(const android::Parcel * input_parcel)1869 android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) {
1870 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1871
1872 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1873 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1874 return -ENODEV;
1875 }
1876
1877 uint32_t mode = UINT32(input_parcel->readInt32());
1878 return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayBuiltIn::SET_DISPLAY_MODE, mode);
1879 }
1880
SetMaxMixerStages(const android::Parcel * input_parcel)1881 android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) {
1882 DisplayError error = kErrorNone;
1883 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1884 uint32_t max_mixer_stages = UINT32(input_parcel->readInt32());
1885 android::status_t status = 0;
1886
1887 for (uint32_t i = 0; i < 32 && bit_mask_display_type[i]; i++) {
1888 int disp_idx = GetDisplayIndex(INT(i));
1889 if (disp_idx == -1) {
1890 continue;
1891 }
1892 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1893 auto &hwc_display = hwc_display_[disp_idx];
1894 if (!hwc_display) {
1895 DLOGW("Display = %d is not connected.", disp_idx);
1896 status = (status)? status : -ENODEV; // Return higher priority error.
1897 continue;
1898 }
1899
1900 error = hwc_display->SetMaxMixerStages(max_mixer_stages);
1901 if (error != kErrorNone) {
1902 status = -EINVAL;
1903 }
1904 }
1905
1906 return status;
1907 }
1908
SetFrameDumpConfig(const android::Parcel * input_parcel)1909 android::status_t HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) {
1910 uint32_t frame_dump_count = UINT32(input_parcel->readInt32());
1911 std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32());
1912 uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32());
1913 int32_t output_format = HAL_PIXEL_FORMAT_RGB_888;
1914 bool post_processed = true;
1915
1916 // Output buffer dump is not supported, if External or Virtual display is present.
1917 bool output_buffer_dump = bit_mask_layer_type & (1 << OUTPUT_LAYER_DUMP);
1918 if (output_buffer_dump) {
1919 int external_dpy_index = GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
1920 int virtual_dpy_index = GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
1921 if (((external_dpy_index != -1) && hwc_display_[external_dpy_index]) ||
1922 ((virtual_dpy_index != -1) && hwc_display_[virtual_dpy_index])) {
1923 DLOGW("Output buffer dump is not supported with External or Virtual display!");
1924 return -EINVAL;
1925 }
1926 }
1927
1928 // Read optional user preferences: output_format and post_processed.
1929 if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1930 // HAL Pixel Format for output buffer
1931 output_format = input_parcel->readInt32();
1932 }
1933 if (input_parcel->dataPosition() != input_parcel->dataSize()) {
1934 // Option to dump Layer Mixer output (0) or DSPP output (1)
1935 post_processed = (input_parcel->readInt32() != 0);
1936 }
1937
1938 android::status_t status = 0;
1939
1940 for (uint32_t i = 0; i < bit_mask_display_type.size(); i++) {
1941 if (!bit_mask_display_type[i]) {
1942 continue;
1943 }
1944 int disp_idx = GetDisplayIndex(INT(i));
1945 if (disp_idx == -1) {
1946 continue;
1947 }
1948 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
1949 auto &hwc_display = hwc_display_[disp_idx];
1950 if (!hwc_display) {
1951 DLOGW("Display = %d is not connected.", disp_idx);
1952 status = (status)? status : -ENODEV; // Return higher priority error.
1953 continue;
1954 }
1955
1956 HWC2::Error error = hwc_display->SetFrameDumpConfig(frame_dump_count, bit_mask_layer_type,
1957 output_format, post_processed);
1958 if (error != HWC2::Error::None) {
1959 status = (HWC2::Error::NoResources == error) ? -ENOMEM : -EINVAL;
1960 }
1961 }
1962
1963 return status;
1964 }
1965
SetMixerResolution(const android::Parcel * input_parcel)1966 android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) {
1967 DisplayError error = kErrorNone;
1968 uint32_t dpy = UINT32(input_parcel->readInt32());
1969
1970 if (dpy != HWC_DISPLAY_PRIMARY) {
1971 DLOGW("Resolution change not supported for this display = %d", dpy);
1972 return -EINVAL;
1973 }
1974
1975 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
1976 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
1977 DLOGW("Primary display is not initialized");
1978 return -ENODEV;
1979 }
1980
1981 uint32_t width = UINT32(input_parcel->readInt32());
1982 uint32_t height = UINT32(input_parcel->readInt32());
1983
1984 error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetMixerResolution(width, height);
1985 if (error != kErrorNone) {
1986 return -EINVAL;
1987 }
1988
1989 return 0;
1990 }
1991
SetColorModeOverride(const android::Parcel * input_parcel)1992 android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) {
1993 int display = static_cast<int>(input_parcel->readInt32());
1994 auto mode = static_cast<ColorMode>(input_parcel->readInt32());
1995
1996 int disp_idx = GetDisplayIndex(display);
1997 if (disp_idx == -1) {
1998 DLOGE("Invalid display = %d", display);
1999 return -EINVAL;
2000 }
2001
2002 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
2003 DLOGE("Invalid ColorMode: %d", mode);
2004 return HWC2_ERROR_BAD_PARAMETER;
2005 }
2006 auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx), &HWCDisplay::SetColorMode,
2007 mode);
2008 if (err != HWC2_ERROR_NONE)
2009 return -EINVAL;
2010
2011 return 0;
2012 }
2013
SetAd4RoiConfig(const android::Parcel * input_parcel)2014 android::status_t HWCSession::SetAd4RoiConfig(const android::Parcel *input_parcel) {
2015 auto display_id = static_cast<uint32_t>(input_parcel->readInt32());
2016 auto h_s = static_cast<uint32_t>(input_parcel->readInt32());
2017 auto h_e = static_cast<uint32_t>(input_parcel->readInt32());
2018 auto v_s = static_cast<uint32_t>(input_parcel->readInt32());
2019 auto v_e = static_cast<uint32_t>(input_parcel->readInt32());
2020 auto f_in = static_cast<uint32_t>(input_parcel->readInt32());
2021 auto f_out = static_cast<uint32_t>(input_parcel->readInt32());
2022
2023 return static_cast<android::status_t>(SetDisplayDppsAdROI(display_id, h_s, h_e, v_s,
2024 v_e, f_in, f_out));
2025 }
2026
SetFrameTriggerMode(const android::Parcel * input_parcel)2027 android::status_t HWCSession::SetFrameTriggerMode(const android::Parcel *input_parcel) {
2028 auto display_id = static_cast<int>(input_parcel->readInt32());
2029 auto mode = static_cast<uint32_t>(input_parcel->readInt32());
2030
2031 int disp_idx = GetDisplayIndex(display_id);
2032 if (disp_idx == -1) {
2033 DLOGE("Invalid display = %d", display_id);
2034 return -EINVAL;
2035 }
2036
2037 auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2038 &HWCDisplay::SetFrameTriggerMode, mode);
2039 if (err != HWC2_ERROR_NONE)
2040 return -EINVAL;
2041
2042 return 0;
2043 }
2044
SetColorModeWithRenderIntentOverride(const android::Parcel * input_parcel)2045 android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
2046 const android::Parcel *input_parcel) {
2047 auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
2048 auto mode = static_cast<ColorMode>(input_parcel->readInt32());
2049 auto int_intent = static_cast<int>(input_parcel->readInt32());
2050
2051 if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_BT2020) {
2052 DLOGE("Invalid ColorMode: %d", mode);
2053 return HWC2_ERROR_BAD_PARAMETER;
2054 }
2055
2056 if ((int_intent < 0) || (int_intent > MAX_EXTENDED_RENDER_INTENT)) {
2057 DLOGE("Invalid RenderIntent: %d", int_intent);
2058 return HWC2_ERROR_BAD_PARAMETER;
2059 }
2060
2061 auto intent = static_cast<RenderIntent>(int_intent);
2062 auto err =
2063 CallDisplayFunction(display, &HWCDisplay::SetColorModeWithRenderIntent, mode, intent);
2064 if (err != HWC2_ERROR_NONE)
2065 return -EINVAL;
2066
2067 return 0;
2068 }
SetColorModeById(const android::Parcel * input_parcel)2069 android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parcel) {
2070 int display = input_parcel->readInt32();
2071 auto mode = input_parcel->readInt32();
2072
2073 int disp_idx = GetDisplayIndex(display);
2074 if (disp_idx == -1) {
2075 DLOGE("Invalid display = %d", display);
2076 return -EINVAL;
2077 }
2078
2079 auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2080 &HWCDisplay::SetColorModeById, mode);
2081 if (err != HWC2_ERROR_NONE)
2082 return -EINVAL;
2083
2084 return 0;
2085 }
2086
SetColorModeFromClient(const android::Parcel * input_parcel)2087 android::status_t HWCSession::SetColorModeFromClient(const android::Parcel *input_parcel) {
2088 int display = input_parcel->readInt32();
2089 auto mode = input_parcel->readInt32();
2090
2091 int disp_idx = GetDisplayIndex(display);
2092 if (disp_idx == -1) {
2093 DLOGE("Invalid display = %d", display);
2094 return -EINVAL;
2095 }
2096
2097 auto err = CallDisplayFunction(static_cast<hwc2_display_t>(disp_idx),
2098 &HWCDisplay::SetColorModeFromClientApi, mode);
2099 if (err != HWC2_ERROR_NONE)
2100 return -EINVAL;
2101
2102 callbacks_.Refresh(static_cast<hwc2_display_t>(disp_idx));
2103
2104 return 0;
2105 }
2106
RefreshScreen(const android::Parcel * input_parcel)2107 android::status_t HWCSession::RefreshScreen(const android::Parcel *input_parcel) {
2108 int display = input_parcel->readInt32();
2109
2110 int disp_idx = GetDisplayIndex(display);
2111 if (disp_idx == -1) {
2112 DLOGE("Invalid display = %d", display);
2113 return -EINVAL;
2114 }
2115
2116 callbacks_.Refresh(static_cast<hwc2_display_t>(disp_idx));
2117
2118 return 0;
2119 }
2120
DynamicDebug(const android::Parcel * input_parcel)2121 void HWCSession::DynamicDebug(const android::Parcel *input_parcel) {
2122 int type = input_parcel->readInt32();
2123 bool enable = (input_parcel->readInt32() > 0);
2124 DLOGI("type = %d enable = %d", type, enable);
2125 int verbose_level = input_parcel->readInt32();
2126
2127 switch (type) {
2128 case qService::IQService::DEBUG_ALL:
2129 HWCDebugHandler::DebugAll(enable, verbose_level);
2130 break;
2131
2132 case qService::IQService::DEBUG_MDPCOMP:
2133 HWCDebugHandler::DebugStrategy(enable, verbose_level);
2134 HWCDebugHandler::DebugCompManager(enable, verbose_level);
2135 break;
2136
2137 case qService::IQService::DEBUG_PIPE_LIFECYCLE:
2138 HWCDebugHandler::DebugResources(enable, verbose_level);
2139 HWCDebugHandler::DebugQos(enable, verbose_level);
2140 break;
2141
2142 case qService::IQService::DEBUG_DRIVER_CONFIG:
2143 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2144 break;
2145
2146 case qService::IQService::DEBUG_ROTATOR:
2147 HWCDebugHandler::DebugResources(enable, verbose_level);
2148 HWCDebugHandler::DebugDriverConfig(enable, verbose_level);
2149 HWCDebugHandler::DebugRotator(enable, verbose_level);
2150 HWCDebugHandler::DebugQos(enable, verbose_level);
2151 break;
2152
2153 case qService::IQService::DEBUG_QDCM:
2154 HWCDebugHandler::DebugQdcm(enable, verbose_level);
2155 break;
2156
2157 case qService::IQService::DEBUG_SCALAR:
2158 HWCDebugHandler::DebugScalar(enable, verbose_level);
2159 break;
2160
2161 case qService::IQService::DEBUG_CLIENT:
2162 HWCDebugHandler::DebugClient(enable, verbose_level);
2163 break;
2164
2165 case qService::IQService::DEBUG_DISPLAY:
2166 HWCDebugHandler::DebugDisplay(enable, verbose_level);
2167 break;
2168
2169 default:
2170 DLOGW("type = %d is not supported", type);
2171 }
2172 }
2173
QdcmCMDDispatch(uint32_t display_id,const PPDisplayAPIPayload & req_payload,PPDisplayAPIPayload * resp_payload,PPPendingParams * pending_action)2174 android::status_t HWCSession::QdcmCMDDispatch(uint32_t display_id,
2175 const PPDisplayAPIPayload &req_payload,
2176 PPDisplayAPIPayload *resp_payload,
2177 PPPendingParams *pending_action) {
2178 int ret = 0;
2179 bool is_physical_display = false;
2180
2181 if (display_id >= HWCCallbacks::kNumDisplays || !hwc_display_[display_id]) {
2182 DLOGW("Invalid display id or display = %d is not connected.", display_id);
2183 return -ENODEV;
2184 }
2185
2186 if (display_id == map_info_primary_.client_id) {
2187 is_physical_display = true;
2188 } else {
2189 for (auto &map_info : map_info_builtin_) {
2190 if (map_info.client_id == display_id) {
2191 is_physical_display = true;
2192 break;
2193 }
2194 }
2195 }
2196
2197 if (!is_physical_display) {
2198 DLOGW("Skipping QDCM command dispatch on display = %d", display_id);
2199 return ret;
2200 }
2201
2202 ret = hwc_display_[display_id]->ColorSVCRequestRoute(req_payload, resp_payload, pending_action);
2203
2204 return ret;
2205 }
2206
QdcmCMDHandler(const android::Parcel * input_parcel,android::Parcel * output_parcel)2207 android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel,
2208 android::Parcel *output_parcel) {
2209 int ret = 0;
2210 float *brightness = NULL;
2211 uint32_t display_id(0);
2212 PPPendingParams pending_action;
2213 PPDisplayAPIPayload resp_payload, req_payload;
2214 uint8_t *disp_id = NULL;
2215 int32_t *mode_id = NULL;
2216
2217 if (!color_mgr_) {
2218 DLOGW("color_mgr_ not initialized.");
2219 return -ENOENT;
2220 }
2221
2222 pending_action.action = kNoAction;
2223 pending_action.params = NULL;
2224
2225 // Read display_id, payload_size and payload from in_parcel.
2226 ret = HWCColorManager::CreatePayloadFromParcel(*input_parcel, &display_id, &req_payload);
2227 if (!ret) {
2228 ret = QdcmCMDDispatch(display_id, req_payload, &resp_payload, &pending_action);
2229 }
2230
2231 if (ret) {
2232 output_parcel->writeInt32(ret); // first field in out parcel indicates return code.
2233 req_payload.DestroyPayload();
2234 resp_payload.DestroyPayload();
2235 return ret;
2236 }
2237
2238 if (kNoAction != pending_action.action) {
2239 int32_t action = pending_action.action;
2240 int count = -1;
2241 while (action > 0) {
2242 count++;
2243 int32_t bit = (action & 1);
2244 action = action >> 1;
2245
2246 if (!bit)
2247 continue;
2248
2249 DLOGV_IF(kTagQDCM, "pending action = %d, display_id = %d", BITMAP(count), display_id);
2250 switch (BITMAP(count)) {
2251 case kInvalidating:
2252 callbacks_.Refresh(display_id);
2253 break;
2254 case kEnterQDCMMode:
2255 ret = color_mgr_->EnableQDCMMode(true, hwc_display_[display_id]);
2256 break;
2257 case kExitQDCMMode:
2258 ret = color_mgr_->EnableQDCMMode(false, hwc_display_[display_id]);
2259 break;
2260 case kApplySolidFill:
2261 {
2262 SCOPE_LOCK(locker_[display_id]);
2263 ret = color_mgr_->SetSolidFill(pending_action.params,
2264 true, hwc_display_[display_id]);
2265 }
2266 callbacks_.Refresh(display_id);
2267 usleep(kSolidFillDelay);
2268 break;
2269 case kDisableSolidFill:
2270 {
2271 SCOPE_LOCK(locker_[display_id]);
2272 ret = color_mgr_->SetSolidFill(pending_action.params,
2273 false, hwc_display_[display_id]);
2274 }
2275 callbacks_.Refresh(display_id);
2276 usleep(kSolidFillDelay);
2277 break;
2278 case kSetPanelBrightness:
2279 ret = -EINVAL;
2280 brightness = reinterpret_cast<float *>(resp_payload.payload);
2281 if (brightness == NULL) {
2282 DLOGE("Brightness payload is Null");
2283 } else {
2284 ret = INT(SetDisplayBrightness(static_cast<hwc2_display_t>(display_id), *brightness));
2285 }
2286 break;
2287 case kEnableFrameCapture:
2288 ret = color_mgr_->SetFrameCapture(pending_action.params, true, hwc_display_[display_id]);
2289 callbacks_.Refresh(display_id);
2290 break;
2291 case kDisableFrameCapture:
2292 ret = color_mgr_->SetFrameCapture(pending_action.params, false,
2293 hwc_display_[display_id]);
2294 break;
2295 case kConfigureDetailedEnhancer:
2296 ret = color_mgr_->SetDetailedEnhancer(pending_action.params, hwc_display_[display_id]);
2297 callbacks_.Refresh(display_id);
2298 break;
2299 case kModeSet:
2300 ret = static_cast<int>
2301 (hwc_display_[display_id]->RestoreColorTransform());
2302 callbacks_.Refresh(display_id);
2303 break;
2304 case kNoAction:
2305 break;
2306 case kMultiDispProc:
2307 for (auto &map_info : map_info_builtin_) {
2308 uint32_t id = UINT32(map_info.client_id);
2309 if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2310 int result = 0;
2311 resp_payload.DestroyPayload();
2312 result = hwc_display_[id]->ColorSVCRequestRoute(req_payload, &resp_payload,
2313 &pending_action);
2314 if (result) {
2315 DLOGW("Failed to dispatch action to disp %d ret %d", id, result);
2316 ret = result;
2317 }
2318 }
2319 }
2320 break;
2321 case kMultiDispGetId:
2322 ret = resp_payload.CreatePayloadBytes(HWCCallbacks::kNumDisplays, &disp_id);
2323 if (ret) {
2324 DLOGW("Unable to create response payload!");
2325 } else {
2326 for (int i = 0; i < HWCCallbacks::kNumDisplays; i++) {
2327 disp_id[i] = HWCCallbacks::kNumDisplays;
2328 }
2329 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
2330 disp_id[HWC_DISPLAY_PRIMARY] = HWC_DISPLAY_PRIMARY;
2331 }
2332 for (auto &map_info : map_info_builtin_) {
2333 uint64_t id = map_info.client_id;
2334 if (id < HWCCallbacks::kNumDisplays && hwc_display_[id]) {
2335 disp_id[id] = (uint8_t)id;
2336 }
2337 }
2338 }
2339 break;
2340 case kSetModeFromClient:
2341 {
2342 SCOPE_LOCK(locker_[display_id]);
2343 mode_id = reinterpret_cast<int32_t *>(resp_payload.payload);
2344 if (mode_id) {
2345 ret = static_cast<int>(hwc_display_[display_id]->SetColorModeFromClientApi(*mode_id));
2346 } else {
2347 DLOGE("mode_id is Null");
2348 ret = -EINVAL;
2349 }
2350 }
2351 if (!ret) {
2352 callbacks_.Refresh(display_id);
2353 }
2354 break;
2355 default:
2356 DLOGW("Invalid pending action = %d!", pending_action.action);
2357 break;
2358 }
2359 }
2360 }
2361 // for display API getter case, marshall returned params into out_parcel.
2362 output_parcel->writeInt32(ret);
2363 HWCColorManager::MarshallStructIntoParcel(resp_payload, output_parcel);
2364 req_payload.DestroyPayload();
2365 resp_payload.DestroyPayload();
2366
2367 SEQUENCE_WAIT_SCOPE_LOCK(locker_[display_id]);
2368 hwc_display_[display_id]->ResetValidation();
2369
2370 return ret;
2371 }
2372
GetEventValue(const char * uevent_data,int length,const char * event_info)2373 int GetEventValue(const char *uevent_data, int length, const char *event_info) {
2374 const char *iterator_str = uevent_data;
2375 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2376 const char *pstr = strstr(iterator_str, event_info);
2377 if (pstr != NULL) {
2378 return (atoi(iterator_str + strlen(event_info)));
2379 }
2380 iterator_str += strlen(iterator_str) + 1;
2381 }
2382
2383 return -1;
2384 }
2385
GetTokenValue(const char * uevent_data,int length,const char * token)2386 const char *GetTokenValue(const char *uevent_data, int length, const char *token) {
2387 const char *iterator_str = uevent_data;
2388 const char *pstr = NULL;
2389 while (((iterator_str - uevent_data) <= length) && (*iterator_str)) {
2390 pstr = strstr(iterator_str, token);
2391 if (pstr) {
2392 break;
2393 }
2394 iterator_str += strlen(iterator_str) + 1;
2395 }
2396
2397 if (pstr)
2398 pstr = pstr+strlen(token);
2399
2400 return pstr;
2401 }
2402
SetDsiClk(const android::Parcel * input_parcel)2403 android::status_t HWCSession::SetDsiClk(const android::Parcel *input_parcel) {
2404 int disp_id = input_parcel->readInt32();
2405 uint64_t clk = UINT64(input_parcel->readInt64());
2406 if (disp_id != HWC_DISPLAY_PRIMARY) {
2407 return -EINVAL;
2408 }
2409
2410 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
2411 if (!hwc_display_[disp_id]) {
2412 return -EINVAL;
2413 }
2414
2415 return hwc_display_[disp_id]->SetDynamicDSIClock(clk);
2416 }
2417
GetDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2418 android::status_t HWCSession::GetDsiClk(const android::Parcel *input_parcel,
2419 android::Parcel *output_parcel) {
2420 int disp_id = input_parcel->readInt32();
2421 if (disp_id != HWC_DISPLAY_PRIMARY) {
2422 return -EINVAL;
2423 }
2424
2425 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
2426 if (!hwc_display_[disp_id]) {
2427 return -EINVAL;
2428 }
2429
2430 uint64_t bitrate = 0;
2431 hwc_display_[disp_id]->GetDynamicDSIClock(&bitrate);
2432 output_parcel->writeUint64(bitrate);
2433
2434 return 0;
2435 }
2436
GetSupportedDsiClk(const android::Parcel * input_parcel,android::Parcel * output_parcel)2437 android::status_t HWCSession::GetSupportedDsiClk(const android::Parcel *input_parcel,
2438 android::Parcel *output_parcel) {
2439 int disp_id = input_parcel->readInt32();
2440 if (disp_id != HWC_DISPLAY_PRIMARY) {
2441 return -EINVAL;
2442 }
2443
2444 SCOPE_LOCK(locker_[disp_id]);
2445 if (!hwc_display_[disp_id]) {
2446 return -EINVAL;
2447 }
2448
2449 std::vector<uint64_t> bit_rates;
2450 hwc_display_[disp_id]->GetSupportedDSIClock(&bit_rates);
2451 output_parcel->writeInt32(INT32(bit_rates.size()));
2452 for (auto &bit_rate : bit_rates) {
2453 output_parcel->writeUint64(bit_rate);
2454 }
2455
2456 return 0;
2457 }
2458
SetPanelLuminanceAttributes(const android::Parcel * input_parcel)2459 android::status_t HWCSession::SetPanelLuminanceAttributes(const android::Parcel *input_parcel) {
2460 int disp_id = input_parcel->readInt32();
2461
2462 // currently doing only for virtual display
2463 if (disp_id != qdutils::DISPLAY_VIRTUAL) {
2464 return -EINVAL;
2465 }
2466
2467 float min_lum = input_parcel->readFloat();
2468 float max_lum = input_parcel->readFloat();
2469
2470 // check for out of range luminance values
2471 if (min_lum <= 0.0f || min_lum >= 1.0f || max_lum <= 100.0f || max_lum >= 1000.0f) {
2472 return -EINVAL;
2473 }
2474
2475 std::lock_guard<std::mutex> obj(mutex_lum_);
2476 set_min_lum_ = min_lum;
2477 set_max_lum_ = max_lum;
2478 DLOGI("set max_lum %f, min_lum %f", set_max_lum_, set_min_lum_);
2479
2480 return 0;
2481 }
2482
UEventHandler(const char * uevent_data,int length)2483 void HWCSession::UEventHandler(const char *uevent_data, int length) {
2484 // Drop hotplug uevents until SurfaceFlinger (the client) is connected. The equivalent of hotplug
2485 // uevent handling will be done once when SurfaceFlinger connects, at RegisterCallback(). Since
2486 // HandlePluggableDisplays() reads the latest connection states of all displays, no uevent is
2487 // lost.
2488 if (callbacks_.IsClientConnected() && strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
2489 // MST hotplug will not carry connection status/test pattern etc.
2490 // Pluggable display handler will check all connection status' and take action accordingly.
2491 const char *str_status = GetTokenValue(uevent_data, length, "status=");
2492 const char *str_mst = GetTokenValue(uevent_data, length, "MST_HOTPLUG=");
2493 if (!str_status && !str_mst) {
2494 return;
2495 }
2496
2497 hpd_bpp_ = GetEventValue(uevent_data, length, "bpp=");
2498 hpd_pattern_ = GetEventValue(uevent_data, length, "pattern=");
2499 DLOGI("Uevent = %s, status = %s, MST_HOTPLUG = %s, bpp = %d, pattern = %d", uevent_data,
2500 str_status ? str_status : "NULL", str_mst ? str_mst : "NULL", hpd_bpp_, hpd_pattern_);
2501
2502 hwc2_display_t virtual_display_index =
2503 (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
2504
2505 std::bitset<kSecureMax> secure_sessions = 0;
2506 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2507 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2508 Locker::ScopeLock lock_a(locker_[active_builtin_disp_id]);
2509 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
2510 }
2511 if (secure_sessions[kSecureDisplay] || hwc_display_[virtual_display_index]) {
2512 // Defer hotplug handling.
2513 SCOPE_LOCK(pluggable_handler_lock_);
2514 DLOGI("Marking hotplug pending...");
2515 pending_hotplug_event_ = kHotPlugEvent;
2516 } else {
2517 // Handle hotplug.
2518 int32_t err = HandlePluggableDisplays(true);
2519 if (err) {
2520 DLOGW("Hotplug handling failed. Error %d '%s'. Hotplug handling %s.", err,
2521 strerror(abs(err)), (pending_hotplug_event_ == kHotPlugEvent) ?
2522 "deferred" : "dropped");
2523 }
2524 }
2525
2526 if (str_status) {
2527 bool connected = (strncmp(str_status, "connected", strlen("connected")) == 0);
2528 DLOGI("Connected = %d", connected);
2529 // Pass on legacy HDMI hot-plug event.
2530 qservice_->onHdmiHotplug(INT(connected));
2531 }
2532 }
2533 }
2534
GetVsyncPeriod(hwc2_display_t disp,uint32_t * vsync_period)2535 int32_t HWCSession::GetVsyncPeriod(hwc2_display_t disp, uint32_t *vsync_period) {
2536 if (disp >= HWCCallbacks::kNumDisplays) {
2537 DLOGW("Invalid Display : display = %" PRIu64, disp);
2538 return HWC2_ERROR_BAD_DISPLAY;
2539 }
2540
2541 SCOPE_LOCK(locker_[(int)disp]);
2542 // default value
2543 *vsync_period = 1000000000ul / 60;
2544
2545 if (hwc_display_[disp]) {
2546 hwc_display_[disp]->GetDisplayAttribute(0, HwcAttribute::VSYNC_PERIOD, (int32_t *)vsync_period);
2547 }
2548
2549 return HWC2_ERROR_NONE;
2550 }
2551
Refresh(hwc2_display_t display)2552 void HWCSession::Refresh(hwc2_display_t display) {
2553 callbacks_.Refresh(display);
2554 }
2555
GetVisibleDisplayRect(const android::Parcel * input_parcel,android::Parcel * output_parcel)2556 android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel,
2557 android::Parcel *output_parcel) {
2558 int disp_idx = GetDisplayIndex(input_parcel->readInt32());
2559 if (disp_idx == -1) {
2560 DLOGE("Invalid display = %d", disp_idx);
2561 return android::BAD_VALUE;
2562 }
2563
2564 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
2565 if (!hwc_display_[disp_idx]) {
2566 return android::NO_INIT;
2567 }
2568
2569 hwc_rect_t visible_rect = {0, 0, 0, 0};
2570 int error = hwc_display_[disp_idx]->GetVisibleDisplayRect(&visible_rect);
2571 if (error < 0) {
2572 return error;
2573 }
2574
2575 output_parcel->writeInt32(visible_rect.left);
2576 output_parcel->writeInt32(visible_rect.top);
2577 output_parcel->writeInt32(visible_rect.right);
2578 output_parcel->writeInt32(visible_rect.bottom);
2579
2580 return android::NO_ERROR;
2581 }
2582
SetStandByMode(const android::Parcel * input_parcel)2583 android::status_t HWCSession::SetStandByMode(const android::Parcel *input_parcel) {
2584 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
2585
2586 bool enable = (input_parcel->readInt32() > 0);
2587
2588 if (!hwc_display_[HWC_DISPLAY_PRIMARY]) {
2589 DLOGI("Primary display is not initialized");
2590 return -EINVAL;
2591 }
2592
2593 hwc_display_[HWC_DISPLAY_PRIMARY]->SetStandByMode(enable);
2594
2595 return android::NO_ERROR;
2596 }
2597
CreatePrimaryDisplay()2598 int HWCSession::CreatePrimaryDisplay() {
2599 int status = -EINVAL;
2600 HWDisplaysInfo hw_displays_info = {};
2601
2602 if (null_display_mode_) {
2603 HWDisplayInfo hw_info = {};
2604 hw_info.display_type = kBuiltIn;
2605 hw_info.is_connected = 1;
2606 hw_info.is_primary = 1;
2607 hw_info.is_wb_ubwc_supported = 0;
2608 hw_info.display_id = 1;
2609 hw_displays_info[hw_info.display_id] = hw_info;
2610 } else {
2611 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2612 if (error != kErrorNone) {
2613 DLOGE("Failed to get connected display list. Error = %d", error);
2614 return status;
2615 }
2616 }
2617
2618 for (auto &iter : hw_displays_info) {
2619 auto &info = iter.second;
2620 if (!info.is_primary) {
2621 continue;
2622 }
2623
2624 // todo (user): If primary display is not connected (e.g. hdmi as primary), a NULL display
2625 // need to be created. SF expects primary display hotplug during callback registration unlike
2626 // previous implementation where first hotplug could be notified anytime.
2627 if (!info.is_connected) {
2628 DLOGE("Primary display is not connected. Not supported at present.");
2629 break;
2630 }
2631
2632 auto hwc_display = &hwc_display_[HWC_DISPLAY_PRIMARY];
2633 hwc2_display_t client_id = map_info_primary_.client_id;
2634
2635 if (info.display_type == kBuiltIn) {
2636 status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2637 qservice_, client_id, info.display_id, hwc_display);
2638 } else if (info.display_type == kPluggable) {
2639 status = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2640 qservice_, client_id, info.display_id, 0, 0, false,
2641 hwc_display);
2642 } else {
2643 DLOGE("Spurious primary display type = %d", info.display_type);
2644 break;
2645 }
2646
2647 if (!status) {
2648 DLOGI("Created primary display type = %d, sdm id = %d, client id = %d", info.display_type,
2649 info.display_id, UINT32(client_id));
2650 {
2651 SCOPE_LOCK(hdr_locker_[client_id]);
2652 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(*hwc_display);
2653 }
2654
2655 map_info_primary_.disp_type = info.display_type;
2656 map_info_primary_.sdm_id = info.display_id;
2657 CreateDummyDisplay(HWC_DISPLAY_PRIMARY);
2658 color_mgr_ = HWCColorManager::CreateColorManager(&buffer_allocator_);
2659 if (!color_mgr_) {
2660 DLOGW("Failed to load HWCColorManager.");
2661 }
2662 } else {
2663 DLOGE("Primary display creation has failed! status = %d", status);
2664 }
2665
2666 // Primary display is found, no need to parse more.
2667 break;
2668 }
2669
2670 return status;
2671 }
2672
CreateDummyDisplay(hwc2_display_t client_id)2673 void HWCSession::CreateDummyDisplay(hwc2_display_t client_id) {
2674 if (!async_powermode_) {
2675 return;
2676 }
2677
2678 hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
2679 auto hwc_display_dummy = &hwc_display_[dummy_disp_id];
2680 HWCDisplayDummy::Create(core_intf_, &buffer_allocator_, &callbacks_, this, qservice_,
2681 0, 0, hwc_display_dummy);
2682 if (!*hwc_display_dummy) {
2683 DLOGE("Dummy display creation failed for %d display\n", UINT32(client_id));
2684 }
2685 }
2686
HandleBuiltInDisplays()2687 int HWCSession::HandleBuiltInDisplays() {
2688 if (null_display_mode_) {
2689 DLOGW("Skipped BuiltIn display handling in null-display mode");
2690 return 0;
2691 }
2692
2693 HWDisplaysInfo hw_displays_info = {};
2694 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2695 if (error != kErrorNone) {
2696 DLOGE("Failed to get connected display list. Error = %d", error);
2697 return -EINVAL;
2698 }
2699
2700 int status = 0;
2701 for (auto &iter : hw_displays_info) {
2702 auto &info = iter.second;
2703
2704 // Do not recreate primary display.
2705 if (info.is_primary || info.display_type != kBuiltIn) {
2706 continue;
2707 }
2708
2709 for (auto &map_info : map_info_builtin_) {
2710 hwc2_display_t client_id = map_info.client_id;
2711
2712 {
2713 SCOPE_LOCK(locker_[client_id]);
2714 // Lock confined to this scope
2715 if (hwc_display_[client_id]) {
2716 continue;
2717 }
2718
2719 DLOGI("Create builtin display, sdm id = %d, client id = %d", info.display_id,
2720 UINT32(client_id));
2721 status = HWCDisplayBuiltIn::Create(core_intf_, &buffer_allocator_, &callbacks_, this,
2722 qservice_, client_id, info.display_id,
2723 &hwc_display_[client_id]);
2724 if (status) {
2725 DLOGE("Builtin display creation failed.");
2726 break;
2727 }
2728
2729 {
2730 SCOPE_LOCK(hdr_locker_[client_id]);
2731 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display_[client_id]);
2732 }
2733
2734 DLOGI("Builtin display created: sdm id = %d, client id = %d", info.display_id,
2735 UINT32(client_id));
2736 map_info.disp_type = info.display_type;
2737 map_info.sdm_id = info.display_id;
2738 CreateDummyDisplay(client_id);
2739 }
2740
2741 DLOGI("Hotplugging builtin display, sdm id = %d, client id = %d", info.display_id,
2742 UINT32(client_id));
2743 callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2744 break;
2745 }
2746 }
2747
2748 return status;
2749 }
2750
HandlePluggableDisplays(bool delay_hotplug)2751 int HWCSession::HandlePluggableDisplays(bool delay_hotplug) {
2752 SCOPE_LOCK(pluggable_handler_lock_);
2753 if (null_display_mode_) {
2754 DLOGW("Skipped pluggable display handling in null-display mode");
2755 return 0;
2756 }
2757
2758 DLOGI("Handling hotplug...");
2759 HWDisplaysInfo hw_displays_info = {};
2760 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
2761 if (error != kErrorNone) {
2762 DLOGE("Failed to get connected display list. Error = %d", error);
2763 return -EINVAL;
2764 }
2765
2766 int status = HandleDisconnectedDisplays(&hw_displays_info);
2767 if (status) {
2768 DLOGE("All displays could not be disconnected.");
2769 return status;
2770 }
2771
2772 status = HandleConnectedDisplays(&hw_displays_info, delay_hotplug);
2773 if (status) {
2774 switch (status) {
2775 case -EAGAIN:
2776 case -ENODEV:
2777 // Errors like device removal or deferral for which we want to try another hotplug handling.
2778 pending_hotplug_event_ = kHotPlugEvent;
2779 status = 0;
2780 break;
2781 default:
2782 // Real errors we want to flag and stop hotplug handling.
2783 pending_hotplug_event_ = kHotPlugNone;
2784 DLOGE("All displays could not be connected. Error %d '%s'.", status, strerror(abs(status)));
2785 }
2786 DLOGI("Handling hotplug... %s", (kHotPlugNone == pending_hotplug_event_) ?
2787 "Stopped." : "Done. Hotplug events pending.");
2788 return status;
2789 }
2790
2791 pending_hotplug_event_ = kHotPlugNone;
2792
2793 DLOGI("Handling hotplug... Done.");
2794 return 0;
2795 }
2796
HandleConnectedDisplays(HWDisplaysInfo * hw_displays_info,bool delay_hotplug)2797 int HWCSession::HandleConnectedDisplays(HWDisplaysInfo *hw_displays_info, bool delay_hotplug) {
2798 int status = 0;
2799 std::vector<hwc2_display_t> pending_hotplugs = {};
2800 hwc2_display_t client_id = 0;
2801
2802 for (auto &iter : *hw_displays_info) {
2803 auto &info = iter.second;
2804
2805 // Do not recreate primary display or if display is not connected.
2806 if (info.is_primary || info.display_type != kPluggable || !info.is_connected) {
2807 continue;
2808 }
2809
2810 // Check if we are already using the display.
2811 auto display_used = std::find_if(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2812 [&](auto &p) {
2813 return (p.sdm_id == info.display_id);
2814 });
2815 if (display_used != map_info_pluggable_.end()) {
2816 // Display is already used in a slot.
2817 continue;
2818 }
2819
2820 // Count active pluggable display slots and slots with no commits.
2821 bool first_commit_pending = false;
2822 std::for_each(map_info_pluggable_.begin(), map_info_pluggable_.end(),
2823 [&](auto &p) {
2824 SCOPE_LOCK(locker_[p.client_id]);
2825 if (hwc_display_[p.client_id]) {
2826 if (!hwc_display_[p.client_id]->IsFirstCommitDone()) {
2827 DLOGI("Display commit pending on display %d-1", p.sdm_id);
2828 first_commit_pending = true;
2829 }
2830 }
2831 });
2832
2833 if (!disable_hotplug_bwcheck_ && first_commit_pending) {
2834 // Hotplug bandwidth check is accomplished by creating and hotplugging a new display after
2835 // a display commit has happened on previous hotplugged displays. This allows the driver to
2836 // return updated modes for the new display based on available link bandwidth.
2837 DLOGI("Pending display commit on one of the displays. Deferring display creation.");
2838 status = -EAGAIN;
2839 if (callbacks_.IsClientConnected()) {
2840 // Trigger a display refresh since we depend on PresentDisplay() to handle pending hotplugs.
2841 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2842 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
2843 active_builtin_disp_id = HWC_DISPLAY_PRIMARY;
2844 }
2845 callbacks_.Refresh(active_builtin_disp_id);
2846 }
2847 break;
2848 }
2849
2850 // find an empty slot to create display.
2851 for (auto &map_info : map_info_pluggable_) {
2852 client_id = map_info.client_id;
2853
2854 // Lock confined to this scope
2855 {
2856 SCOPE_LOCK(locker_[client_id]);
2857 auto &hwc_display = hwc_display_[client_id];
2858 if (hwc_display) {
2859 // Display slot is already used.
2860 continue;
2861 }
2862
2863 DLOGI("Create pluggable display, sdm id = %d, client id = %d", info.display_id,
2864 UINT32(client_id));
2865
2866 // Test pattern generation ?
2867 map_info.test_pattern = (hpd_bpp_ > 0) && (hpd_pattern_ > 0);
2868 int err = 0;
2869 if (!map_info.test_pattern) {
2870 err = HWCDisplayPluggable::Create(core_intf_, &buffer_allocator_,
2871 &callbacks_, this, qservice_, client_id,
2872 info.display_id, 0, 0, false, &hwc_display);
2873 } else {
2874 err = HWCDisplayPluggableTest::Create(core_intf_, &buffer_allocator_,
2875 &callbacks_, this, qservice_, client_id,
2876 info.display_id, UINT32(hpd_bpp_),
2877 UINT32(hpd_pattern_), &hwc_display);
2878 }
2879
2880 if (err) {
2881 DLOGW("Pluggable display creation failed/aborted. Error %d '%s'.", err,
2882 strerror(abs(err)));
2883 status = err;
2884 // Attempt creating remaining pluggable displays.
2885 break;
2886 }
2887
2888 {
2889 SCOPE_LOCK(hdr_locker_[client_id]);
2890 is_hdr_display_[UINT32(client_id)] = HasHDRSupport(hwc_display);
2891 }
2892
2893 DLOGI("Created pluggable display successfully: sdm id = %d, client id = %d",
2894 info.display_id, UINT32(client_id));
2895 CreateDummyDisplay(client_id);
2896 }
2897
2898 map_info.disp_type = info.display_type;
2899 map_info.sdm_id = info.display_id;
2900
2901 pending_hotplugs.push_back((hwc2_display_t)client_id);
2902
2903 // Display is created for this sdm id, move to next connected display.
2904 break;
2905 }
2906 }
2907
2908 // No display was created.
2909 if (!pending_hotplugs.size()) {
2910 return status;
2911 }
2912
2913 // Active builtin display needs revalidation
2914 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
2915 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
2916 WaitForResources(delay_hotplug, active_builtin_disp_id, client_id);
2917 }
2918
2919 for (auto client_id : pending_hotplugs) {
2920 DLOGI("Notify hotplug display connected: client id = %d", UINT32(client_id));
2921 callbacks_.Hotplug(client_id, HWC2::Connection::Connected);
2922 }
2923
2924 return status;
2925 }
2926
HasHDRSupport(HWCDisplay * hwc_display)2927 bool HWCSession::HasHDRSupport(HWCDisplay *hwc_display) {
2928 // query number of hdr types
2929 uint32_t out_num_types = 0;
2930 float out_max_luminance = 0.0f;
2931 float out_max_average_luminance = 0.0f;
2932 float out_min_luminance = 0.0f;
2933 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
2934 &out_max_average_luminance, &out_min_luminance)
2935 != HWC2::Error::None) {
2936 return false;
2937 }
2938
2939 return (out_num_types > 0);
2940 }
2941
HandleDisconnectedDisplays(HWDisplaysInfo * hw_displays_info)2942 int HWCSession::HandleDisconnectedDisplays(HWDisplaysInfo *hw_displays_info) {
2943 // Destroy pluggable displays which were connected earlier but got disconnected now.
2944 for (auto &map_info : map_info_pluggable_) {
2945 bool disconnect = true; // disconnect in case display id is not found in list.
2946
2947 for (auto &iter : *hw_displays_info) {
2948 auto &info = iter.second;
2949 if (info.display_id != map_info.sdm_id) {
2950 continue;
2951 }
2952 if (info.is_connected) {
2953 disconnect = false;
2954 }
2955 break;
2956 }
2957
2958 if (disconnect) {
2959 DestroyDisplay(&map_info);
2960 }
2961 }
2962
2963 return 0;
2964 }
2965
DestroyDisplay(DisplayMapInfo * map_info)2966 void HWCSession::DestroyDisplay(DisplayMapInfo *map_info) {
2967 switch (map_info->disp_type) {
2968 case kPluggable:
2969 DestroyPluggableDisplay(map_info);
2970 break;
2971 default:
2972 DestroyNonPluggableDisplay(map_info);
2973 break;
2974 }
2975 }
2976
DestroyPluggableDisplay(DisplayMapInfo * map_info)2977 void HWCSession::DestroyPluggableDisplay(DisplayMapInfo *map_info) {
2978 hwc2_display_t client_id = map_info->client_id;
2979
2980 DLOGI("Notify hotplug display disconnected: client id = %d", UINT32(client_id));
2981 callbacks_.Hotplug(client_id, HWC2::Connection::Disconnected);
2982
2983 SCOPE_LOCK(system_locker_);
2984 {
2985 SEQUENCE_WAIT_SCOPE_LOCK(locker_[client_id]);
2986 auto &hwc_display = hwc_display_[client_id];
2987 if (!hwc_display) {
2988 return;
2989 }
2990 DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
2991 UINT32(client_id));
2992 {
2993 SCOPE_LOCK(hdr_locker_[client_id]);
2994 is_hdr_display_[UINT32(client_id)] = false;
2995 }
2996
2997 if (!map_info->test_pattern) {
2998 HWCDisplayPluggable::Destroy(hwc_display);
2999 } else {
3000 HWCDisplayPluggableTest::Destroy(hwc_display);
3001 }
3002
3003 if (async_powermode_) {
3004 hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
3005 auto &hwc_display_dummy = hwc_display_[dummy_disp_id];
3006 display_ready_.reset(UINT32(dummy_disp_id));
3007 if (hwc_display_dummy) {
3008 HWCDisplayDummy::Destroy(hwc_display_dummy);
3009 hwc_display_dummy = nullptr;
3010 }
3011 }
3012 display_ready_.reset(UINT32(client_id));
3013 pending_power_mode_[client_id] = false;
3014 hwc_display = nullptr;
3015 map_info->Reset();
3016 }
3017 }
3018
DestroyNonPluggableDisplay(DisplayMapInfo * map_info)3019 void HWCSession::DestroyNonPluggableDisplay(DisplayMapInfo *map_info) {
3020 hwc2_display_t client_id = map_info->client_id;
3021
3022 SCOPE_LOCK(locker_[client_id]);
3023 auto &hwc_display = hwc_display_[client_id];
3024 if (!hwc_display) {
3025 return;
3026 }
3027 DLOGI("Destroy display %d-%d, client id = %d", map_info->sdm_id, map_info->disp_type,
3028 UINT32(client_id));
3029 {
3030 SCOPE_LOCK(hdr_locker_[client_id]);
3031 is_hdr_display_[UINT32(client_id)] = false;
3032 }
3033
3034 switch (map_info->disp_type) {
3035 case kBuiltIn:
3036 HWCDisplayBuiltIn::Destroy(hwc_display);
3037 break;
3038 default:
3039 virtual_display_factory_.Destroy(hwc_display);
3040 break;
3041 }
3042
3043 if (async_powermode_ && map_info->disp_type == kBuiltIn) {
3044 hwc2_display_t dummy_disp_id = map_hwc_display_.find(client_id)->second;
3045 auto &hwc_display_dummy = hwc_display_[dummy_disp_id];
3046 display_ready_.reset(UINT32(dummy_disp_id));
3047 if (hwc_display_dummy) {
3048 HWCDisplayDummy::Destroy(hwc_display_dummy);
3049 hwc_display_dummy = nullptr;
3050 }
3051 }
3052 pending_power_mode_[client_id] = false;
3053 hwc_display = nullptr;
3054 display_ready_.reset(UINT32(client_id));
3055 map_info->Reset();
3056 }
3057
ValidateDisplayInternal(hwc2_display_t display,uint32_t * out_num_types,uint32_t * out_num_requests)3058 HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t *out_num_types,
3059 uint32_t *out_num_requests) {
3060 HWCDisplay *hwc_display = hwc_display_[display];
3061
3062 DTRACE_SCOPED();
3063 if (hwc_display->IsInternalValidateState()) {
3064 // Internal Validation has already been done on display, get the Output params.
3065 return hwc_display->GetValidateDisplayOutput(out_num_types, out_num_requests);
3066 }
3067
3068 if (display == HWC_DISPLAY_PRIMARY) {
3069 // TODO(user): This can be moved to HWCDisplayPrimary
3070 if (need_invalidate_) {
3071 callbacks_.Refresh(display);
3072 need_invalidate_ = false;
3073 }
3074
3075 if (color_mgr_) {
3076 color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]);
3077 }
3078 }
3079
3080 return hwc_display->Validate(out_num_types, out_num_requests);
3081 }
3082
PresentDisplayInternal(hwc2_display_t display)3083 HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display) {
3084 HWCDisplay *hwc_display = hwc_display_[display];
3085
3086 DTRACE_SCOPED();
3087 // If display is in Skip-Validate state and Validate cannot be skipped, do Internal
3088 // Validation to optimize for the frames which don't require the Client composition.
3089 if (hwc_display->IsSkipValidateState() && !hwc_display->CanSkipValidate()) {
3090 uint32_t out_num_types = 0, out_num_requests = 0;
3091 hwc_display->SetFastPathComposition(true);
3092 HWC2::Error error = ValidateDisplayInternal(display, &out_num_types, &out_num_requests);
3093 if ((error != HWC2::Error::None) || hwc_display->HWCClientNeedsValidate()) {
3094 hwc_display->SetValidationState(HWCDisplay::kInternalValidate);
3095 hwc_display->SetFastPathComposition(false);
3096 return HWC2::Error::NotValidated;
3097 }
3098 }
3099 return HWC2::Error::None;
3100 }
3101
DisplayPowerReset()3102 void HWCSession::DisplayPowerReset() {
3103 // Acquire lock on all displays.
3104 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3105 display < HWCCallbacks::kNumDisplays; display++) {
3106 locker_[display].Lock();
3107 }
3108
3109 HWC2::Error status = HWC2::Error::None;
3110 HWC2::PowerMode last_power_mode[HWCCallbacks::kNumDisplays] = {};
3111
3112 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3113 display < HWCCallbacks::kNumDisplays; display++) {
3114 if (hwc_display_[display] != NULL) {
3115 last_power_mode[display] = hwc_display_[display]->GetCurrentPowerMode();
3116 DLOGI("Powering off display = %d", INT32(display));
3117 status = hwc_display_[display]->SetPowerMode(HWC2::PowerMode::Off,
3118 true /* teardown */);
3119 if (status != HWC2::Error::None) {
3120 DLOGE("Power off for display = %d failed with error = %d", INT32(display), status);
3121 }
3122 }
3123 }
3124 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3125 display < HWCCallbacks::kNumDisplays; display++) {
3126 if (hwc_display_[display] != NULL) {
3127 HWC2::PowerMode mode = last_power_mode[display];
3128 DLOGI("Setting display %d to mode = %d", INT32(display), mode);
3129 status = hwc_display_[display]->SetPowerMode(mode, false /* teardown */);
3130 if (status != HWC2::Error::None) {
3131 DLOGE("%d mode for display = %d failed with error = %d", mode, INT32(display), status);
3132 }
3133 ColorMode color_mode = hwc_display_[display]->GetCurrentColorMode();
3134 status = hwc_display_[display]->SetColorMode(color_mode);
3135 if (status != HWC2::Error::None) {
3136 DLOGE("SetColorMode failed for display = %d error = %d", INT32(display), status);
3137 }
3138 }
3139 }
3140
3141 hwc2_display_t vsync_source = callbacks_.GetVsyncSource();
3142 status = hwc_display_[vsync_source]->SetVsyncEnabled(HWC2::Vsync::Enable);
3143 if (status != HWC2::Error::None) {
3144 DLOGE("Enabling vsync failed for disp: %" PRIu64 " with error = %d", vsync_source, status);
3145 }
3146
3147 // Release lock on all displays.
3148 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3149 display < HWCCallbacks::kNumDisplays; display++) {
3150 locker_[display].Unlock();
3151 }
3152
3153 callbacks_.Refresh(vsync_source);
3154 }
3155
HandleSecureSession()3156 void HWCSession::HandleSecureSession() {
3157 std::bitset<kSecureMax> secure_sessions = 0;
3158 {
3159 // TODO(user): Revisit if supporting secure display on non-primary.
3160 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3161 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3162 return;
3163 }
3164 Locker::ScopeLock lock_pwr(power_state_[active_builtin_disp_id]);
3165 if (power_state_transition_[active_builtin_disp_id]) {
3166 // Route all interactions with client to dummy display.
3167 active_builtin_disp_id = map_hwc_display_.find(active_builtin_disp_id)->second;
3168 }
3169 Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3170 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3171 }
3172
3173 if (secure_sessions.any()) {
3174 secure_session_active_ = true;
3175 } else if (!secure_session_active_) {
3176 // No secure session active. No secure session transition to handle. Skip remaining steps.
3177 return;
3178 }
3179
3180 // If it is called during primary prepare/commit, we need to pause any ongoing commit on
3181 // external/virtual display.
3182 bool found_active_secure_display = false;
3183 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY;
3184 display < HWCCallbacks::kNumRealDisplays; display++) {
3185 Locker::ScopeLock lock_d(locker_[display]);
3186 HWCDisplay *hwc_display = hwc_display_[display];
3187 if (!hwc_display || hwc_display->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
3188 continue;
3189 }
3190
3191 bool is_active_secure_display = false;
3192 // The first On/Doze/DozeSuspend built-in display is taken as the secure display.
3193 if (!found_active_secure_display &&
3194 hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3195 is_active_secure_display = true;
3196 found_active_secure_display = true;
3197 }
3198 hwc_display->HandleSecureSession(secure_sessions, &pending_power_mode_[display],
3199 is_active_secure_display);
3200 }
3201 }
3202
HandlePendingPowerMode(hwc2_display_t disp_id,const shared_ptr<Fence> & retire_fence)3203 void HWCSession::HandlePendingPowerMode(hwc2_display_t disp_id,
3204 const shared_ptr<Fence> &retire_fence) {
3205 if (!secure_session_active_) {
3206 // No secure session active. Skip remaining steps.
3207 return;
3208 }
3209
3210 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3211 if (disp_id != active_builtin_disp_id) {
3212 return;
3213 }
3214
3215 Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3216 bool pending_power_mode = false;
3217 std::bitset<kSecureMax> secure_sessions = 0;
3218 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3219 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
3220 display < HWCCallbacks::kNumDisplays; display++) {
3221 if (display != active_builtin_disp_id) {
3222 Locker::ScopeLock lock_d(locker_[display]);
3223 if (pending_power_mode_[display]) {
3224 pending_power_mode = true;
3225 break;
3226 }
3227 }
3228 }
3229
3230 if (!pending_power_mode) {
3231 if (!secure_sessions.any()) {
3232 secure_session_active_ = false;
3233 }
3234 return;
3235 }
3236
3237 // retire fence is set only after successful primary commit, So check for retire fence to know
3238 // non secure commit went through to notify driver to change the CRTC mode to non secure.
3239 // Otherwise any commit to non-primary display would fail.
3240 if (retire_fence == nullptr) {
3241 return;
3242 }
3243
3244 Fence::Wait(retire_fence);
3245
3246 for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1;
3247 display < HWCCallbacks::kNumDisplays; display++) {
3248 if (display != active_builtin_disp_id) {
3249 Locker::ScopeLock lock_d(locker_[display]);
3250 if (pending_power_mode_[display] && hwc_display_[display]) {
3251 HWC2::Error error =
3252 hwc_display_[display]->SetPowerMode(hwc_display_[display]->GetPendingPowerMode(), false);
3253 if (HWC2::Error::None == error) {
3254 pending_power_mode_[display] = false;
3255 hwc_display_[display]->ClearPendingPowerMode();
3256 pending_refresh_.set(UINT32(HWC_DISPLAY_PRIMARY));
3257 } else {
3258 DLOGE("SetDisplayStatus error = %d (%s)", error, to_string(error).c_str());
3259 }
3260 }
3261 }
3262 }
3263 secure_session_active_ = false;
3264 }
3265
HandlePendingHotplug(hwc2_display_t disp_id,const shared_ptr<Fence> & retire_fence)3266 void HWCSession::HandlePendingHotplug(hwc2_display_t disp_id,
3267 const shared_ptr<Fence> &retire_fence) {
3268 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
3269 if (disp_id != active_builtin_disp_id ||
3270 (kHotPlugNone == pending_hotplug_event_ && !destroy_virtual_disp_pending_)) {
3271 return;
3272 }
3273
3274 std :: bitset < kSecureMax > secure_sessions = 0;
3275 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
3276 Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
3277 hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
3278 }
3279
3280 if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
3281 return;
3282 }
3283
3284 if (destroy_virtual_disp_pending_ || kHotPlugEvent == pending_hotplug_event_) {
3285 Fence::Wait(retire_fence);
3286
3287 // Destroy the pending virtual display if secure session not present.
3288 if (destroy_virtual_disp_pending_) {
3289 for (auto &map_info : map_info_virtual_) {
3290 DestroyDisplay(&map_info);
3291 destroy_virtual_disp_pending_ = false;
3292 virtual_id_ = HWCCallbacks::kNumDisplays;
3293 }
3294 }
3295 // Handle connect/disconnect hotplugs if secure session is not present.
3296 hwc2_display_t virtual_display_idx = (hwc2_display_t)GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3297 if (!hwc_display_[virtual_display_idx] && kHotPlugEvent == pending_hotplug_event_) {
3298 // Handle deferred hotplug event.
3299 int32_t err = pluggable_handler_lock_.TryLock();
3300 if (!err) {
3301 // Do hotplug handling in a different thread to avoid blocking PresentDisplay.
3302 std::thread(&HWCSession::HandlePluggableDisplays, this, true).detach();
3303 pluggable_handler_lock_.Unlock();
3304 } else {
3305 // EBUSY means another thread is already handling hotplug. Skip deferred hotplug handling.
3306 if (EBUSY != err) {
3307 DLOGW("Failed to acquire pluggable display handler lock. Error %d '%s'.", err,
3308 strerror(abs(err)));
3309 }
3310 }
3311 }
3312 }
3313 }
3314
GetReadbackBufferAttributes(hwc2_display_t display,int32_t * format,int32_t * dataspace)3315 int32_t HWCSession::GetReadbackBufferAttributes(hwc2_display_t display, int32_t *format,
3316 int32_t *dataspace) {
3317 if (display >= HWCCallbacks::kNumDisplays) {
3318 return HWC2_ERROR_BAD_DISPLAY;
3319 }
3320
3321 if (!format || !dataspace) {
3322 return HWC2_ERROR_BAD_PARAMETER;
3323 }
3324
3325 if (display != HWC_DISPLAY_PRIMARY) {
3326 return HWC2_ERROR_UNSUPPORTED;
3327 }
3328
3329 HWCDisplay *hwc_display = hwc_display_[display];
3330 if (hwc_display == nullptr) {
3331 return HWC2_ERROR_BAD_DISPLAY;
3332 } else if (!hwc_display->HasReadBackBufferSupport()) {
3333 return HWC2_ERROR_UNSUPPORTED;
3334 }
3335
3336 *format = HAL_PIXEL_FORMAT_RGB_888;
3337 *dataspace = GetDataspaceFromColorMode(hwc_display->GetCurrentColorMode());
3338
3339 return HWC2_ERROR_NONE;
3340 }
3341
SetReadbackBuffer(hwc2_display_t display,const native_handle_t * buffer,const shared_ptr<Fence> & acquire_fence)3342 int32_t HWCSession::SetReadbackBuffer(hwc2_display_t display, const native_handle_t *buffer,
3343 const shared_ptr<Fence> &acquire_fence) {
3344
3345 if (display >= HWCCallbacks::kNumDisplays) {
3346 return HWC2_ERROR_BAD_DISPLAY;
3347 }
3348
3349 if (!buffer) {
3350 return HWC2_ERROR_BAD_PARAMETER;
3351 }
3352
3353 if (display != HWC_DISPLAY_PRIMARY) {
3354 return HWC2_ERROR_UNSUPPORTED;
3355 }
3356
3357 int external_dpy_index = GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
3358 int virtual_dpy_index = GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
3359 if (((external_dpy_index != -1) && hwc_display_[external_dpy_index]) ||
3360 ((virtual_dpy_index != -1) && hwc_display_[virtual_dpy_index])) {
3361 return HWC2_ERROR_UNSUPPORTED;
3362 }
3363
3364 return CallDisplayFunction(display, &HWCDisplay::SetReadbackBuffer, buffer, acquire_fence,
3365 false, kCWBClientComposer);
3366 }
3367
GetReadbackBufferFence(hwc2_display_t display,shared_ptr<Fence> * release_fence)3368 int32_t HWCSession::GetReadbackBufferFence(hwc2_display_t display,
3369 shared_ptr<Fence> *release_fence) {
3370 if (display >= HWCCallbacks::kNumDisplays) {
3371 return HWC2_ERROR_BAD_DISPLAY;
3372 }
3373
3374 if (!release_fence) {
3375 return HWC2_ERROR_BAD_PARAMETER;
3376 }
3377
3378 if (display != HWC_DISPLAY_PRIMARY) {
3379 return HWC2_ERROR_UNSUPPORTED;
3380 }
3381
3382 return CallDisplayFunction(display, &HWCDisplay::GetReadbackBufferFence, release_fence);
3383 }
3384
GetDisplayIdentificationData(hwc2_display_t display,uint8_t * outPort,uint32_t * outDataSize,uint8_t * outData)3385 int32_t HWCSession::GetDisplayIdentificationData(hwc2_display_t display, uint8_t *outPort,
3386 uint32_t *outDataSize, uint8_t *outData) {
3387 if (!outPort || !outDataSize) {
3388 return HWC2_ERROR_BAD_PARAMETER;
3389 }
3390
3391 if (display >= HWCCallbacks::kNumDisplays) {
3392 return HWC2_ERROR_BAD_DISPLAY;
3393 }
3394
3395 return CallDisplayFunction(display, &HWCDisplay::GetDisplayIdentificationData, outPort,
3396 outDataSize, outData);
3397 }
3398
GetDisplayCapabilities(hwc2_display_t display,uint32_t * outNumCapabilities,uint32_t * outCapabilities)3399 int32_t HWCSession::GetDisplayCapabilities(hwc2_display_t display, uint32_t *outNumCapabilities,
3400 uint32_t *outCapabilities) {
3401 if (!outNumCapabilities) {
3402 return HWC2_ERROR_BAD_PARAMETER;
3403 }
3404
3405 if (display >= HWCCallbacks::kNumDisplays) {
3406 return HWC2_ERROR_BAD_DISPLAY;
3407 }
3408
3409 if (!hwc_display_[display]) {
3410 DLOGE("Expected valid hwc_display");
3411 return HWC2_ERROR_BAD_PARAMETER;
3412 }
3413
3414 bool isBuiltin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3415 *outNumCapabilities = 0;
3416 if (isBuiltin) {
3417 *outNumCapabilities = 3;
3418 if (outCapabilities != nullptr) {
3419 // TODO(user): Handle SKIP_CLIENT_COLOR_TRANSFORM based on DSPP availability
3420 outCapabilities[0] = static_cast<uint32_t>(HwcDisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM);
3421 outCapabilities[1] = static_cast<uint32_t>(HwcDisplayCapability::DOZE);
3422 outCapabilities[2] = static_cast<uint32_t>(HwcDisplayCapability::BRIGHTNESS);
3423 }
3424 }
3425
3426 return HWC2_ERROR_NONE;
3427 }
3428
GetDisplayCapabilities_2_4(hwc2_display_t display,uint32_t * outNumCapabilities,uint32_t * outCapabilities)3429 int32_t HWCSession::GetDisplayCapabilities_2_4(hwc2_display_t display, uint32_t *outNumCapabilities,
3430 uint32_t *outCapabilities) {
3431 if (!outNumCapabilities) {
3432 return HWC2_ERROR_BAD_PARAMETER;
3433 }
3434
3435 if (display >= HWCCallbacks::kNumDisplays) {
3436 return HWC2_ERROR_BAD_DISPLAY;
3437 }
3438
3439 if (!hwc_display_[display]) {
3440 DLOGE("Expected valid hwc_display");
3441 return HWC2_ERROR_BAD_PARAMETER;
3442 }
3443
3444 bool isBuiltin = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3445 *outNumCapabilities = 0;
3446 if (isBuiltin) {
3447 *outNumCapabilities = 1;
3448 if (outCapabilities != nullptr) {
3449 outCapabilities[0] = static_cast<uint32_t>(HwcDisplayCapability::PROTECTED_CONTENTS);
3450 }
3451 }
3452
3453 return HWC2_ERROR_NONE;
3454 }
3455
GetDisplayConnectionType(hwc2_display_t display,HwcDisplayConnectionType * type)3456 int32_t HWCSession::GetDisplayConnectionType(hwc2_display_t display,
3457 HwcDisplayConnectionType *type) {
3458 if (display >= HWCCallbacks::kNumDisplays) {
3459 return HWC2_ERROR_BAD_DISPLAY;
3460 }
3461
3462 if (!type) {
3463 return HWC2_ERROR_BAD_PARAMETER;
3464 }
3465
3466 if (!hwc_display_[display]) {
3467 DLOGE("Expected valid hwc_display");
3468 return HWC2_ERROR_BAD_DISPLAY;
3469 }
3470 *type = HwcDisplayConnectionType::EXTERNAL;
3471 if (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
3472 *type = HwcDisplayConnectionType::INTERNAL;
3473 }
3474
3475 return HWC2_ERROR_NONE;
3476 }
3477
GetDisplayBrightnessSupport(hwc2_display_t display,bool * outSupport)3478 int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_display_t display, bool *outSupport) {
3479 if (!outSupport) {
3480 return HWC2_ERROR_BAD_PARAMETER;
3481 }
3482
3483 if (display >= HWCCallbacks::kNumDisplays) {
3484 return HWC2_ERROR_BAD_DISPLAY;
3485 }
3486
3487 if (!hwc_display_[display]) {
3488 DLOGE("Expected valid hwc_display");
3489 return HWC2_ERROR_BAD_PARAMETER;
3490 }
3491 *outSupport = (hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN);
3492 return HWC2_ERROR_NONE;
3493 }
3494
SetDisplayBrightness(hwc2_display_t display,float brightness)3495 int32_t HWCSession::SetDisplayBrightness(hwc2_display_t display, float brightness) {
3496 if (display >= HWCCallbacks::kNumDisplays) {
3497 return HWC2_ERROR_BAD_DISPLAY;
3498 }
3499
3500 if (!hwc_display_[display]) {
3501 return HWC2_ERROR_BAD_PARAMETER;
3502 }
3503
3504 return INT32(hwc_display_[display]->SetPanelBrightness(brightness));
3505 }
3506
SetQSyncMode(const android::Parcel * input_parcel)3507 android::status_t HWCSession::SetQSyncMode(const android::Parcel *input_parcel) {
3508 auto mode = input_parcel->readInt32();
3509
3510 QSyncMode qsync_mode = kQSyncModeNone;
3511 switch (mode) {
3512 case qService::IQService::QSYNC_MODE_NONE:
3513 qsync_mode = kQSyncModeNone;
3514 break;
3515 case qService::IQService::QSYNC_MODE_CONTINUOUS:
3516 qsync_mode = kQSyncModeContinuous;
3517 break;
3518 case qService::IQService::QSYNC_MODE_ONESHOT:
3519 qsync_mode = kQsyncModeOneShot;
3520 break;
3521 default:
3522 DLOGE("Qsync mode not supported %d", mode);
3523 return -EINVAL;
3524 }
3525 return CallDisplayFunction(HWC_DISPLAY_PRIMARY, &HWCDisplay::SetQSyncMode, qsync_mode);
3526 }
3527
UpdateThrottlingRate()3528 void HWCSession::UpdateThrottlingRate() {
3529 uint32_t new_min = 0;
3530
3531 for (int i=0; i < HWCCallbacks::kNumDisplays; i++) {
3532 auto &display = hwc_display_[i];
3533 if (!display)
3534 continue;
3535 if (display->GetCurrentPowerMode() != HWC2::PowerMode::Off)
3536 new_min = (new_min == 0) ? display->GetMaxRefreshRate() :
3537 std::min(new_min, display->GetMaxRefreshRate());
3538 }
3539
3540 SetNewThrottlingRate(new_min);
3541 }
3542
SetNewThrottlingRate(const uint32_t new_rate)3543 void HWCSession::SetNewThrottlingRate(const uint32_t new_rate) {
3544 if (new_rate !=0 && throttling_refresh_rate_ != new_rate) {
3545 HWCDisplay::SetThrottlingRefreshRate(new_rate);
3546 throttling_refresh_rate_ = new_rate;
3547 }
3548 }
3549
SetIdlePC(const android::Parcel * input_parcel)3550 android::status_t HWCSession::SetIdlePC(const android::Parcel *input_parcel) {
3551 auto enable = input_parcel->readInt32();
3552 auto synchronous = input_parcel->readInt32();
3553
3554 return static_cast<android::status_t>(ControlIdlePowerCollapse(enable, synchronous));
3555 }
3556
GetActiveBuiltinDisplay()3557 hwc2_display_t HWCSession::GetActiveBuiltinDisplay() {
3558 hwc2_display_t active_display = HWCCallbacks::kNumDisplays;
3559 // Get first active display among primary and built-in displays.
3560 std::vector<DisplayMapInfo> map_info = {map_info_primary_};
3561 std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
3562
3563 for (auto &info : map_info) {
3564 hwc2_display_t target_display = info.client_id;
3565 SCOPE_LOCK(power_state_[target_display]);
3566 if (power_state_transition_[target_display]) {
3567 // Route all interactions with client to dummy display.
3568 target_display = map_hwc_display_.find(target_display)->second;
3569 }
3570 Locker::ScopeLock lock_d(locker_[target_display]);
3571 auto &hwc_display = hwc_display_[target_display];
3572 if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3573 active_display = info.client_id;
3574 break;
3575 }
3576 }
3577
3578 return active_display;
3579 }
3580
SetDisplayBrightnessScale(const android::Parcel * input_parcel)3581 int32_t HWCSession::SetDisplayBrightnessScale(const android::Parcel *input_parcel) {
3582 auto display = input_parcel->readInt32();
3583 auto level = input_parcel->readInt32();
3584 if (level < 0 || level > kBrightnessScaleMax) {
3585 DLOGE("Invalid backlight scale level %d", level);
3586 return -EINVAL;
3587 }
3588 auto bl_scale = level * kSvBlScaleMax / kBrightnessScaleMax;
3589 auto error = CallDisplayFunction(display, &HWCDisplay::SetBLScale, (uint32_t)bl_scale);
3590 if (INT32(error) == HWC2_ERROR_NONE) {
3591 callbacks_.Refresh(display);
3592 }
3593
3594 return INT32(error);
3595 }
3596
NotifyClientStatus(bool connected)3597 void HWCSession::NotifyClientStatus(bool connected) {
3598 for (uint32_t i = 0; i < HWCCallbacks::kNumDisplays; i++) {
3599 if (!hwc_display_[i]) {
3600 continue;
3601 }
3602 SCOPE_LOCK(locker_[i]);
3603 hwc_display_[i]->NotifyClientStatus(connected);
3604 hwc_display_[i]->SetVsyncEnabled(HWC2::Vsync::Disable);
3605 }
3606 callbacks_.UpdateVsyncSource(HWCCallbacks::kNumDisplays);
3607 }
3608
WaitForResources(bool wait_for_resources,hwc2_display_t active_builtin_id,hwc2_display_t display_id)3609 void HWCSession::WaitForResources(bool wait_for_resources, hwc2_display_t active_builtin_id,
3610 hwc2_display_t display_id) {
3611 std::vector<DisplayMapInfo> map_info = {map_info_primary_};
3612 std::copy(map_info_builtin_.begin(), map_info_builtin_.end(), std::back_inserter(map_info));
3613
3614 for (auto &info : map_info) {
3615 hwc2_display_t target_display = info.client_id;
3616 {
3617 SCOPE_LOCK(power_state_[target_display]);
3618 if (power_state_transition_[target_display]) {
3619 // Route all interactions with client to dummy display.
3620 target_display = map_hwc_display_.find(target_display)->second;
3621 }
3622 }
3623 {
3624 SEQUENCE_WAIT_SCOPE_LOCK(locker_[target_display]);
3625 auto &hwc_display = hwc_display_[target_display];
3626 if (hwc_display && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) {
3627 hwc_display->ResetValidation();
3628 }
3629 }
3630 }
3631
3632 if (wait_for_resources) {
3633 bool res_wait = true;
3634 do {
3635 if (client_connected_) {
3636 Refresh(active_builtin_id);
3637 }
3638 {
3639 std::unique_lock<std::mutex> caller_lock(hotplug_mutex_);
3640 hotplug_cv_.wait(caller_lock);
3641 }
3642 res_wait = hwc_display_[display_id]->CheckResourceState();
3643 } while (res_wait);
3644 }
3645 }
3646
GetDisplayVsyncPeriod(hwc2_display_t disp,VsyncPeriodNanos * vsync_period)3647 int32_t HWCSession::GetDisplayVsyncPeriod(hwc2_display_t disp, VsyncPeriodNanos *vsync_period) {
3648 if (vsync_period == nullptr) {
3649 return HWC2_ERROR_BAD_PARAMETER;
3650 }
3651
3652 return CallDisplayFunction(disp, &HWCDisplay::GetDisplayVsyncPeriod, vsync_period);
3653 }
3654
SetActiveConfigWithConstraints(hwc2_display_t display,hwc2_config_t config,const VsyncPeriodChangeConstraints * vsync_period_change_constraints,VsyncPeriodChangeTimeline * out_timeline)3655 int32_t HWCSession::SetActiveConfigWithConstraints(
3656 hwc2_display_t display, hwc2_config_t config,
3657 const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
3658 VsyncPeriodChangeTimeline *out_timeline) {
3659 if ((vsync_period_change_constraints == nullptr) || (out_timeline == nullptr)) {
3660 return HWC2_ERROR_BAD_PARAMETER;
3661 }
3662
3663 return CallDisplayFunction(display, &HWCDisplay::SetActiveConfigWithConstraints, config,
3664 vsync_period_change_constraints, out_timeline);
3665 }
3666
SetAutoLowLatencyMode(hwc2_display_t display,bool on)3667 int32_t HWCSession::SetAutoLowLatencyMode(hwc2_display_t display, bool on) {
3668 if (display >= HWCCallbacks::kNumDisplays) {
3669 return HWC2_ERROR_BAD_DISPLAY;
3670 }
3671
3672 return CallDisplayFunction(display, &HWCDisplay::SetAutoLowLatencyMode, on);
3673 }
3674
GetSupportedContentTypes(hwc2_display_t display,hidl_vec<HwcContentType> * types)3675 int32_t HWCSession::GetSupportedContentTypes(hwc2_display_t display,
3676 hidl_vec<HwcContentType> *types) {
3677 if (display >= HWCCallbacks::kNumDisplays) {
3678 return HWC2_ERROR_BAD_DISPLAY;
3679 }
3680
3681 return CallDisplayFunction(display, &HWCDisplay::GetSupportedContentTypes, types);
3682 }
3683
SetContentType(hwc2_display_t display,HwcContentType type)3684 int32_t HWCSession::SetContentType(hwc2_display_t display, HwcContentType type) {
3685 if (display >= HWCCallbacks::kNumDisplays) {
3686 return HWC2_ERROR_BAD_DISPLAY;
3687 }
3688
3689 return CallDisplayFunction(display, &HWCDisplay::SetContentType, type);
3690 }
3691
IsHbmSupported()3692 bool HWCSession::IsHbmSupported() {
3693 auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
3694
3695 if (hwc_display)
3696 return hwc_display->IsHbmSupported();
3697
3698 return 0;
3699 }
3700
SetHbmState(HbmState state)3701 void HWCSession::SetHbmState(HbmState state) {
3702 CallDisplayFunction(HWC_DISPLAY_PRIMARY, &HWCDisplay::SetHbm, state, HWCDisplay::APP);
3703 }
3704
GetHbmState()3705 HbmState HWCSession::GetHbmState() {
3706 auto hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
3707
3708 if (hwc_display)
3709 return hwc_display->GetHbm();
3710
3711 return HbmState::OFF;
3712 }
3713
IsLbeSupported()3714 bool HWCSession::IsLbeSupported() {
3715 return (is_lbe_supported_ != 0);
3716 }
3717
SetLbeState(LbeState state)3718 void HWCSession::SetLbeState(LbeState state) {
3719 std::string_view state_cmd;
3720 int ret = 0;
3721
3722 if (!is_lbe_supported_) {
3723 DLOGE("lbe is not supported");
3724 return;
3725 }
3726
3727 if (lbe_cur_state_ == state)
3728 return;
3729
3730 switch (state) {
3731 case LbeState::OFF:
3732 state_cmd = ltm_off_cmd_;
3733 break;
3734 case LbeState::NORMAL:
3735 state_cmd = ltm_default_mode_cmd_;
3736 break;
3737 case LbeState::HIGH_BRIGHTNESS:
3738 state_cmd = ltm_hbm_mode_cmd_;
3739 break;
3740 case LbeState::POWER_SAVE:
3741 state_cmd = ltm_power_save_mode_cmd_;
3742 break;
3743 default:
3744 DLOGE("lbe mode not support");
3745 return;
3746 }
3747
3748 if (lbe_cur_state_ == LbeState::OFF) {
3749 std::string_view on_cmd = ltm_on_cmd_;
3750 ret = SendLTMCommand(on_cmd.data());
3751 if (ret) {
3752 DLOGE("failed to enable lbe");
3753 return;
3754 }
3755 }
3756
3757 ret = SendLTMCommand(state_cmd.data());
3758 if (!ret)
3759 lbe_cur_state_ = state;
3760 }
3761
SetLbeAmbientLight(int value)3762 void HWCSession::SetLbeAmbientLight(int value) {
3763 if (!is_lbe_supported_ || value < 0 || (lbe_cur_state_ == LbeState::OFF))
3764 return;
3765
3766 std::string cmd = ltm_lux_cmd_;
3767 std::string val = std::to_string(value);
3768
3769 cmd += val;
3770
3771 SendLTMCommand(cmd.c_str());
3772 }
3773
GetLbeState()3774 LbeState HWCSession::GetLbeState() {
3775 return lbe_cur_state_;
3776 }
3777
SendLTMCommand(const char * cmd)3778 int HWCSession::SendLTMCommand(const char *cmd) {
3779 if (!cmd || !pps_retry)
3780 return -EINVAL;
3781
3782 while ((pps_retry > 0) && (pps_socket_ < 0)) {
3783 pps_socket_ = socket_local_client("pps", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
3784 if (pps_socket_ < 0) {
3785 pps_retry--;
3786 if (pps_retry == 0) {
3787 DLOGE("Connecting to pps socket failed, error = %s", strerror(errno));
3788 return -ETIMEDOUT;
3789 }
3790 }
3791 }
3792
3793 int ret = write(pps_socket_, cmd, strlen(cmd));
3794 if (ret < 0) {
3795 DLOGE("Failed to send LTM cmd, error = %s", strerror(errno));
3796 return -EINVAL;
3797 }
3798 usleep(1000);
3799
3800 return 0;
3801 }
3802
3803 } // namespace sdm
3804