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