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