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