1 /*
2 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *    * Redistributions of source code must retain the above copyright
8 *      notice, this list of conditions and the following disclaimer.
9 *    * Redistributions in binary form must reproduce the above
10 *      copyright notice, this list of conditions and the following
11 *      disclaimer in the documentation and/or other materials provided
12 *      with the distribution.
13 *    * Neither the name of The Linux Foundation. nor the names of its
14 *      contributors may be used to endorse or promote products derived
15 *      from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include <core/buffer_allocator.h>
31 #include <utils/debug.h>
32 #include <utils/constants.h>
33 #include <sync/sync.h>
34 #include <vector>
35 #include <string>
36 
37 #include "hwc_buffer_sync_handler.h"
38 #include "hwc_session.h"
39 #include "hwc_debugger.h"
40 
41 #define __CLASS__ "HWCSession"
42 
43 namespace sdm {
44 
StartServices()45 void HWCSession::StartServices() {
46   int error = DisplayConfig::DeviceInterface::RegisterDevice(this);
47   if (error) {
48     DLOGW("Could not register IDisplayConfig as service (%d).", error);
49   } else {
50     DLOGI("IDisplayConfig service registration completed.");
51   }
52 }
53 
MapDisplayType(DispType dpy)54 int MapDisplayType(DispType dpy) {
55   switch (dpy) {
56     case DispType::kPrimary:
57       return qdutils::DISPLAY_PRIMARY;
58 
59     case DispType::kExternal:
60       return qdutils::DISPLAY_EXTERNAL;
61 
62     case DispType::kVirtual:
63       return qdutils::DISPLAY_VIRTUAL;
64 
65     default:
66       break;
67   }
68 
69   return -EINVAL;
70 }
71 
WaitForResourceNeeded(HWC2::PowerMode prev_mode,HWC2::PowerMode new_mode)72 bool WaitForResourceNeeded(HWC2::PowerMode prev_mode, HWC2::PowerMode new_mode) {
73   return ((prev_mode == HWC2::PowerMode::Off) &&
74           (new_mode == HWC2::PowerMode::On || new_mode == HWC2::PowerMode::Doze));
75 }
76 
MapExternalStatus(DisplayConfig::ExternalStatus status)77 HWCDisplay::DisplayStatus MapExternalStatus(DisplayConfig::ExternalStatus status) {
78   switch (status) {
79     case DisplayConfig::ExternalStatus::kOffline:
80       return HWCDisplay::kDisplayStatusOffline;
81 
82     case DisplayConfig::ExternalStatus::kOnline:
83       return HWCDisplay::kDisplayStatusOnline;
84 
85     case DisplayConfig::ExternalStatus::kPause:
86       return HWCDisplay::kDisplayStatusPause;
87 
88     case DisplayConfig::ExternalStatus::kResume:
89       return HWCDisplay::kDisplayStatusResume;
90 
91     default:
92       break;
93   }
94 
95   return HWCDisplay::kDisplayStatusInvalid;
96 }
97 
RegisterClientContext(std::shared_ptr<DisplayConfig::ConfigCallback> callback,DisplayConfig::ConfigInterface ** intf)98 int HWCSession::RegisterClientContext(std::shared_ptr<DisplayConfig::ConfigCallback> callback,
99                                       DisplayConfig::ConfigInterface **intf) {
100   if (!intf) {
101     DLOGE("Invalid DisplayConfigIntf location");
102     return -EINVAL;
103   }
104 
105   std::weak_ptr<DisplayConfig::ConfigCallback> wp_callback = callback;
106   DisplayConfigImpl *impl = new DisplayConfigImpl(wp_callback, this);
107   *intf = impl;
108 
109   return 0;
110 }
111 
UnRegisterClientContext(DisplayConfig::ConfigInterface * intf)112 void HWCSession::UnRegisterClientContext(DisplayConfig::ConfigInterface *intf) {
113   delete static_cast<DisplayConfigImpl *>(intf);
114 }
115 
DisplayConfigImpl(std::weak_ptr<DisplayConfig::ConfigCallback> callback,HWCSession * hwc_session)116 HWCSession::DisplayConfigImpl::DisplayConfigImpl(
117                                std::weak_ptr<DisplayConfig::ConfigCallback> callback,
118                                HWCSession *hwc_session) {
119   callback_ = callback;
120   hwc_session_ = hwc_session;
121 }
122 
IsDisplayConnected(DispType dpy,bool * connected)123 int HWCSession::DisplayConfigImpl::IsDisplayConnected(DispType dpy, bool *connected) {
124   int disp_id = MapDisplayType(dpy);
125   int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
126 
127   if (disp_idx == -1) {
128     DLOGE("Invalid display = %d", disp_id);
129     return -EINVAL;
130   } else {
131     SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_idx]);
132     *connected = hwc_session_->hwc_display_[disp_idx];
133   }
134 
135   return 0;
136 }
137 
SetDisplayStatus(int disp_id,HWCDisplay::DisplayStatus status)138 int HWCSession::SetDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
139   int disp_idx = GetDisplayIndex(disp_id);
140   int err = -EINVAL;
141   if (disp_idx == -1) {
142     DLOGE("Invalid display = %d", disp_id);
143     return -EINVAL;
144   }
145 
146   if (disp_idx == qdutils::DISPLAY_PRIMARY) {
147     DLOGE("Not supported for this display");
148     return err;
149   }
150 
151   {
152     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
153     if (!hwc_display_[disp_idx]) {
154       DLOGW("Display is not connected");
155       return err;
156     }
157     DLOGI("Display = %d, Status = %d", disp_idx, status);
158     err = hwc_display_[disp_idx]->SetDisplayStatus(status);
159     if (err != 0) {
160       return err;
161     }
162   }
163 
164   if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
165     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
166     if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
167       {
168         SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
169         hwc_display_[active_builtin_disp_id]->ResetValidation();
170       }
171       callbacks_.Refresh(active_builtin_disp_id);
172     }
173   }
174 
175   return err;
176 }
177 
SetDisplayStatus(DispType dpy,DisplayConfig::ExternalStatus status)178 int HWCSession::DisplayConfigImpl::SetDisplayStatus(DispType dpy,
179                                                     DisplayConfig::ExternalStatus status) {
180   return hwc_session_->SetDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
181 }
182 
ConfigureDynRefreshRate(DisplayConfig::DynRefreshRateOp op,uint32_t refresh_rate)183 int HWCSession::DisplayConfigImpl::ConfigureDynRefreshRate(DisplayConfig::DynRefreshRateOp op,
184                                                            uint32_t refresh_rate) {
185   SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
186   HWCDisplay *hwc_display = hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY];
187 
188   if (!hwc_display) {
189     DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
190     return -EINVAL;
191   }
192 
193   switch (op) {
194     case DisplayConfig::DynRefreshRateOp::kDisableMetadata:
195       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
196 
197     case DisplayConfig::DynRefreshRateOp::kEnableMetadata:
198       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
199 
200     case DisplayConfig::DynRefreshRateOp::kSetBinder:
201       return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refresh_rate);
202 
203     default:
204       DLOGW("Invalid operation %d", op);
205       return -EINVAL;
206   }
207 
208   return 0;
209 }
210 
GetConfigCount(int disp_id,uint32_t * count)211 int HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
212   int disp_idx = GetDisplayIndex(disp_id);
213   if (disp_idx == -1) {
214     DLOGE("Invalid display = %d", disp_id);
215     return -EINVAL;
216   }
217 
218   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
219 
220   if (hwc_display_[disp_idx]) {
221     return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
222   }
223 
224   return -EINVAL;
225 }
226 
GetConfigCount(DispType dpy,uint32_t * count)227 int HWCSession::DisplayConfigImpl::GetConfigCount(DispType dpy, uint32_t *count) {
228   return hwc_session_->GetConfigCount(MapDisplayType(dpy), count);
229 }
230 
GetActiveConfigIndex(int disp_id,uint32_t * config)231 int HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
232   int disp_idx = GetDisplayIndex(disp_id);
233   if (disp_idx == -1) {
234     DLOGE("Invalid display = %d", disp_id);
235     return -EINVAL;
236   }
237 
238   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
239 
240   if (hwc_display_[disp_idx]) {
241     return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
242   }
243 
244   return -EINVAL;
245 }
246 
GetActiveConfig(DispType dpy,uint32_t * config)247 int HWCSession::DisplayConfigImpl::GetActiveConfig(DispType dpy, uint32_t *config) {
248   return hwc_session_->GetActiveConfigIndex(MapDisplayType(dpy), config);
249 }
250 
SetActiveConfigIndex(int disp_id,uint32_t config)251 int HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
252   int disp_idx = GetDisplayIndex(disp_id);
253   if (disp_idx == -1) {
254     DLOGE("Invalid display = %d", disp_id);
255     return -EINVAL;
256   }
257 
258   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
259   int error = -EINVAL;
260   if (hwc_display_[disp_idx]) {
261     error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
262     if (!error) {
263       callbacks_.Refresh(0);
264     }
265   }
266 
267   return error;
268 }
269 
SetActiveConfig(DispType dpy,uint32_t config)270 int HWCSession::DisplayConfigImpl::SetActiveConfig(DispType dpy, uint32_t config) {
271   return hwc_session_->SetActiveConfigIndex(MapDisplayType(dpy), config);
272 }
273 
GetDisplayAttributes(uint32_t config_index,DispType dpy,DisplayConfig::Attributes * attributes)274 int HWCSession::DisplayConfigImpl::GetDisplayAttributes(uint32_t config_index, DispType dpy,
275                                                         DisplayConfig::Attributes *attributes) {
276   int error = -EINVAL;
277   int disp_id = MapDisplayType(dpy);
278   int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
279 
280   if (disp_idx == -1) {
281     DLOGE("Invalid display = %d", disp_id);
282   } else {
283     SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_idx]);
284     if (hwc_session_->hwc_display_[disp_idx]) {
285       DisplayConfigVariableInfo var_info;
286       error = hwc_session_->hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(config_index),
287                                                                                   &var_info);
288       if (!error) {
289         attributes->vsync_period = var_info.vsync_period_ns;
290         attributes->x_res = var_info.x_pixels;
291         attributes->y_res = var_info.y_pixels;
292         attributes->x_dpi = var_info.x_dpi;
293         attributes->y_dpi = var_info.y_dpi;
294         attributes->panel_type = DisplayConfig::DisplayPortType::kDefault;
295         attributes->is_yuv = var_info.is_yuv;
296       }
297     }
298   }
299 
300   return error;
301 }
302 
SetPanelBrightness(uint32_t level)303 int HWCSession::DisplayConfigImpl::SetPanelBrightness(uint32_t level) {
304   if (!(0 <= level && level <= 255)) {
305     return -EINVAL;
306   }
307 
308   if (level == 0) {
309     return INT32(hwc_session_->SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f));
310   } else {
311     return INT32(hwc_session_->SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f));
312   }
313 }
314 
GetPanelBrightness(uint32_t * level)315 int HWCSession::DisplayConfigImpl::GetPanelBrightness(uint32_t *level) {
316   float brightness = -1.0f;
317   int error = -EINVAL;
318 
319   error = hwc_session_->getDisplayBrightness(HWC_DISPLAY_PRIMARY, &brightness);
320   if (brightness == -1.0f) {
321     *level = 0;
322   } else {
323     *level = static_cast<uint32_t>(254.0f*brightness + 1);
324   }
325 
326   return error;
327 }
328 
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)329 int HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
330   DLOGI("Display %d", disp_id);
331 
332   // SSG team hardcoded disp_id as external because it applies to external only but SSG team sends
333   // this level irrespective of external connected or not. So to honor the call, make disp_id to
334   // primary & set level.
335   disp_id = HWC_DISPLAY_PRIMARY;
336   int disp_idx = GetDisplayIndex(disp_id);
337   if (disp_idx == -1) {
338     DLOGE("Invalid display = %d", disp_id);
339     return -EINVAL;
340   }
341 
342   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
343   HWCDisplay *hwc_display = hwc_display_[disp_idx];
344   if (!hwc_display) {
345     DLOGE("Display = %d is not connected.", disp_idx);
346     return -EINVAL;
347   }
348 
349   return hwc_display->OnMinHdcpEncryptionLevelChange(min_enc_level);
350 }
351 
MinHdcpEncryptionLevelChanged(DispType dpy,uint32_t min_enc_level)352 int HWCSession::DisplayConfigImpl::MinHdcpEncryptionLevelChanged(DispType dpy,
353                                                                  uint32_t min_enc_level) {
354   return hwc_session_->MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
355 }
356 
RefreshScreen()357 int HWCSession::DisplayConfigImpl::RefreshScreen() {
358   SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
359   hwc_session_->callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
360   return 0;
361 }
362 
ControlPartialUpdate(int disp_id,bool enable)363 int HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
364   int disp_idx = GetDisplayIndex(disp_id);
365   if (disp_idx == -1) {
366     DLOGE("Invalid display = %d", disp_id);
367     return -EINVAL;
368   }
369 
370   if (disp_idx != HWC_DISPLAY_PRIMARY) {
371     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
372     return -EINVAL;
373   }
374 
375   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
376   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
377   if (!hwc_display) {
378     DLOGE("primary display object is not instantiated");
379     return -EINVAL;
380   }
381 
382   uint32_t pending = 0;
383   DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
384 
385   if (hwc_error == kErrorNone) {
386     if (!pending) {
387       return 0;
388     }
389   } else if (hwc_error == kErrorNotSupported) {
390     return 0;
391   } else {
392     return -EINVAL;
393   }
394 
395   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
396   callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
397 
398   // Wait until partial update control is complete
399   int error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
400 
401   return error;
402 }
403 
ControlPartialUpdate(DispType dpy,bool enable)404 int HWCSession::DisplayConfigImpl::ControlPartialUpdate(DispType dpy, bool enable) {
405   return hwc_session_->ControlPartialUpdate(MapDisplayType(dpy), enable);
406 }
407 
ToggleScreenUpdate(bool on)408 int HWCSession::ToggleScreenUpdate(bool on) {
409   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
410 
411   int error = -EINVAL;
412   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
413     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
414     if (error) {
415       DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
416     }
417   }
418 
419   return error;
420 }
421 
ToggleScreenUpdate(bool on)422 int HWCSession::DisplayConfigImpl::ToggleScreenUpdate(bool on) {
423   return hwc_session_->ToggleScreenUpdate(on);
424 }
425 
SetIdleTimeout(uint32_t value)426 int HWCSession::SetIdleTimeout(uint32_t value) {
427   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
428 
429   int inactive_ms = IDLE_TIMEOUT_INACTIVE_MS;
430   Debug::Get()->GetProperty(IDLE_TIME_INACTIVE_PROP, &inactive_ms);
431   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
432     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value, inactive_ms);
433     return 0;
434   }
435 
436   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
437   return -ENODEV;
438 }
439 
SetIdleTimeout(uint32_t value)440 int HWCSession::DisplayConfigImpl::SetIdleTimeout(uint32_t value) {
441   return hwc_session_->SetIdleTimeout(value);
442 }
443 
GetHDRCapabilities(DispType dpy,DisplayConfig::HDRCapsParams * caps)444 int HWCSession::DisplayConfigImpl::GetHDRCapabilities(DispType dpy,
445                                                       DisplayConfig::HDRCapsParams *caps) {
446   int error = -EINVAL;
447 
448   do {
449     int disp_id = MapDisplayType(dpy);
450     int disp_idx = hwc_session_->GetDisplayIndex(disp_id);
451     if (disp_idx == -1) {
452       DLOGE("Invalid display = %d", disp_id);
453       break;
454     }
455 
456     SCOPE_LOCK(hwc_session_->locker_[disp_id]);
457     HWCDisplay *hwc_display = hwc_session_->hwc_display_[disp_idx];
458     if (!hwc_display) {
459       DLOGW("Display = %d is not connected.", disp_idx);
460       error = -ENODEV;
461       break;
462     }
463 
464     // query number of hdr types
465     uint32_t out_num_types = 0;
466     float out_max_luminance = 0.0f;
467     float out_max_average_luminance = 0.0f;
468     float out_min_luminance = 0.0f;
469     if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
470                                         &out_max_average_luminance, &out_min_luminance)
471                                         != HWC2::Error::None) {
472       break;
473     }
474     if (!out_num_types) {
475       error = 0;
476       break;
477     }
478 
479     // query hdr caps
480     caps->supported_hdr_types.resize(out_num_types);
481 
482     if (hwc_display->GetHdrCapabilities(&out_num_types, caps->supported_hdr_types.data(),
483                                         &out_max_luminance, &out_max_average_luminance,
484                                         &out_min_luminance) == HWC2::Error::None) {
485       error = 0;
486     }
487   } while (false);
488 
489   return error;
490 }
491 
SetCameraLaunchStatus(uint32_t on)492 int HWCSession::SetCameraLaunchStatus(uint32_t on) {
493   if (null_display_mode_) {
494     return 0;
495   }
496 
497   if (!core_intf_) {
498     DLOGW("core_intf_ not initialized.");
499     return -ENOENT;
500   }
501 
502   HWBwModes mode = on > 0 ? kBwVFEOn : kBwVFEOff;
503 
504   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
505     return -EINVAL;
506   }
507 
508   // trigger invalidate to apply new bw caps.
509   callbacks_.Refresh(0);
510 
511   return 0;
512 }
513 
SetCameraLaunchStatus(uint32_t on)514 int HWCSession::DisplayConfigImpl::SetCameraLaunchStatus(uint32_t on) {
515   return hwc_session_->SetCameraLaunchStatus(on);
516 }
517 
518 #ifdef DISPLAY_CONFIG_CAMERA_SMOOTH_APIs_1_0
SetCameraSmoothInfo(CameraSmoothOp op,uint32_t fps)519 int HWCSession::DisplayConfigImpl::SetCameraSmoothInfo(CameraSmoothOp op, uint32_t fps) {
520   std::shared_ptr<DisplayConfig::ConfigCallback> callback = hwc_session_->camera_callback_.lock();
521   if (!callback) {
522     return -EAGAIN;
523   }
524 
525   callback->NotifyCameraSmoothInfo(op, fps);
526 
527   return 0;
528 }
529 
ControlCameraSmoothCallback(bool enable)530 int HWCSession::DisplayConfigImpl::ControlCameraSmoothCallback(bool enable) {
531   if (enable) {
532     hwc_session_->camera_callback_ = callback_;
533   } else {
534     hwc_session_->camera_callback_.reset();
535   }
536 
537   return 0;
538 }
539 #endif
540 
DisplayBWTransactionPending(bool * status)541 int HWCSession::DisplayBWTransactionPending(bool *status) {
542   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
543 
544   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
545     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
546       DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
547       *status = false;
548     }
549 
550     return 0;
551   }
552 
553   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
554   return -ENODEV;
555 }
556 
DisplayBWTransactionPending(bool * status)557 int HWCSession::DisplayConfigImpl::DisplayBWTransactionPending(bool *status) {
558   return hwc_session_->DisplayBWTransactionPending(status);
559 }
560 
ControlIdlePowerCollapse(bool enable,bool synchronous)561 int HWCSession::ControlIdlePowerCollapse(bool enable, bool synchronous) {
562   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
563   if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
564     DLOGE("No active displays");
565     return -EINVAL;
566   }
567   SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
568 
569   if (hwc_display_[active_builtin_disp_id]) {
570     if (!enable) {
571       if (!idle_pc_ref_cnt_) {
572         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
573                                                                                   synchronous);
574         if (err != kErrorNone) {
575           return (err == kErrorNotSupported) ? 0 : -EINVAL;
576         }
577         callbacks_.Refresh(active_builtin_disp_id);
578         int error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
579         if (error == ETIMEDOUT) {
580           DLOGE("Timed out!! Next frame commit done event not received!!");
581           return error;
582         }
583         DLOGI("Idle PC disabled!!");
584       }
585       idle_pc_ref_cnt_++;
586     } else if (idle_pc_ref_cnt_ > 0) {
587       if (!(idle_pc_ref_cnt_ - 1)) {
588         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
589                                                                                   synchronous);
590         if (err != kErrorNone) {
591           return (err == kErrorNotSupported) ? 0 : -EINVAL;
592         }
593         DLOGI("Idle PC enabled!!");
594       }
595       idle_pc_ref_cnt_--;
596     }
597     return 0;
598   }
599 
600   DLOGW("Display = %d is not connected.", UINT32(active_builtin_disp_id));
601   return -ENODEV;
602 }
603 
ControlIdlePowerCollapse(bool enable,bool synchronous)604 int HWCSession::DisplayConfigImpl::ControlIdlePowerCollapse(bool enable, bool synchronous) {
605   return hwc_session_->ControlIdlePowerCollapse(enable, synchronous);
606 }
607 
IsWbUbwcSupported(bool * value)608 int HWCSession::IsWbUbwcSupported(bool *value) {
609   HWDisplaysInfo hw_displays_info = {};
610   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
611   if (error != kErrorNone) {
612     return -EINVAL;
613   }
614 
615   for (auto &iter : hw_displays_info) {
616     auto &info = iter.second;
617     if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
618       *value = 1;
619     }
620   }
621 
622   return error;
623 }
624 
getDisplayBrightness(uint32_t display,float * brightness)625 int32_t HWCSession::getDisplayBrightness(uint32_t display, float *brightness) {
626   if (!brightness) {
627     return HWC2_ERROR_BAD_PARAMETER;
628   }
629 
630   if (display >= HWCCallbacks::kNumDisplays) {
631     return HWC2_ERROR_BAD_DISPLAY;
632   }
633 
634   SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
635   int32_t error = -EINVAL;
636   *brightness = -1.0f;
637 
638   HWCDisplay *hwc_display = hwc_display_[display];
639   if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
640     error = INT32(hwc_display_[display]->GetPanelBrightness(brightness));
641     if (error) {
642       DLOGE("Failed to get the panel brightness. Error = %d", error);
643     }
644   }
645 
646   return error;
647 }
648 
getDisplayMaxBrightness(uint32_t display,uint32_t * max_brightness_level)649 int32_t HWCSession::getDisplayMaxBrightness(uint32_t display, uint32_t *max_brightness_level) {
650   if (!max_brightness_level) {
651     return HWC2_ERROR_BAD_PARAMETER;
652   }
653 
654   if (display >= HWCCallbacks::kNumDisplays) {
655     return HWC2_ERROR_BAD_DISPLAY;
656   }
657 
658   int32_t error = -EINVAL;
659   HWCDisplay *hwc_display = hwc_display_[display];
660   if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
661     error = INT32(hwc_display_[display]->GetPanelMaxBrightness(max_brightness_level));
662     if (error) {
663       DLOGE("Failed to get the panel max brightness, display %u error %d", display, error);
664     }
665   }
666 
667   return error;
668 }
669 
SetDisplayAnimating(uint64_t display_id,bool animating)670 int HWCSession::DisplayConfigImpl::SetDisplayAnimating(uint64_t display_id, bool animating) {
671   return hwc_session_->CallDisplayFunction(display_id, &HWCDisplay::SetDisplayAnimating, animating);
672 }
673 
GetWriteBackCapabilities(bool * isWbUbwcSupported)674 int HWCSession::DisplayConfigImpl::GetWriteBackCapabilities(bool *isWbUbwcSupported) {
675   return hwc_session_->IsWbUbwcSupported(isWbUbwcSupported);
676 }
677 
SetDisplayDppsAdROI(uint32_t display_id,uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)678 int HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
679                                     uint32_t h_end, uint32_t v_start, uint32_t v_end,
680                                     uint32_t factor_in, uint32_t factor_out) {
681   return CallDisplayFunction(display_id,
682                              &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
683                              factor_in, factor_out);
684 }
685 
SetDisplayDppsAdROI(uint32_t display_id,uint32_t h_start,uint32_t h_end,uint32_t v_start,uint32_t v_end,uint32_t factor_in,uint32_t factor_out)686 int HWCSession::DisplayConfigImpl::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
687                                                        uint32_t h_end, uint32_t v_start,
688                                                        uint32_t v_end, uint32_t factor_in,
689                                                        uint32_t factor_out) {
690   return hwc_session_->SetDisplayDppsAdROI(display_id, h_start, h_end, v_start, v_end,
691                                            factor_in, factor_out);
692 }
693 
UpdateVSyncSourceOnPowerModeOff()694 int HWCSession::DisplayConfigImpl::UpdateVSyncSourceOnPowerModeOff() {
695   hwc_session_->update_vsync_on_power_off_ = true;
696   return 0;
697 }
698 
UpdateVSyncSourceOnPowerModeDoze()699 int HWCSession::DisplayConfigImpl::UpdateVSyncSourceOnPowerModeDoze() {
700   hwc_session_->update_vsync_on_doze_ = true;
701   return 0;
702 }
703 
IsPowerModeOverrideSupported(uint32_t disp_id,bool * supported)704 int HWCSession::DisplayConfigImpl::IsPowerModeOverrideSupported(uint32_t disp_id,
705                                                                 bool *supported) {
706   if (!hwc_session_->async_powermode_ || (disp_id > HWCCallbacks::kNumRealDisplays)) {
707     *supported = false;
708   } else {
709     *supported = true;
710   }
711 
712   return 0;
713 }
714 
SetPowerMode(uint32_t disp_id,DisplayConfig::PowerMode power_mode)715 int HWCSession::DisplayConfigImpl::SetPowerMode(uint32_t disp_id,
716                                                 DisplayConfig::PowerMode power_mode) {
717   SCOPE_LOCK(hwc_session_->display_config_locker_);
718 
719   bool supported = false;
720   IsPowerModeOverrideSupported(disp_id, &supported);
721   if (!supported) {
722     return 0;
723   }
724   // Added this flag for pixel
725   hwc_session_->async_power_mode_triggered_  = true;
726   // Active builtin display needs revalidation
727   hwc2_display_t active_builtin_disp_id = hwc_session_->GetActiveBuiltinDisplay();
728   HWC2::PowerMode previous_mode = hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode();
729 
730   DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
731   auto mode = static_cast<HWC2::PowerMode>(power_mode);
732 
733   HWCDisplay::HWCLayerStack stack = {};
734   hwc2_display_t dummy_disp_id = hwc_session_->map_hwc_display_.at(disp_id);
735 
736   // Power state transition start.
737   // Acquire the display's power-state transition var read lock.
738   hwc_session_->power_state_[disp_id].Lock();
739   hwc_session_->power_state_transition_[disp_id] = true;
740   hwc_session_->locker_[disp_id].Lock();        // Lock the real display.
741   hwc_session_->locker_[dummy_disp_id].Lock();  // Lock the corresponding dummy display.
742 
743   // Place the real display's layer-stack on the dummy display.
744   hwc_session_->hwc_display_[disp_id]->GetLayerStack(&stack);
745   hwc_session_->hwc_display_[dummy_disp_id]->SetLayerStack(&stack);
746   hwc_session_->hwc_display_[dummy_disp_id]->UpdatePowerMode(
747                                        hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode());
748 
749   buffer_handle_t target = 0;
750   shared_ptr<Fence> acquire_fence = nullptr;
751   int32_t dataspace = 0;
752   hwc_region_t damage = {};
753   VsyncPeriodNanos vsync_period = 16600000;
754   hwc_session_->hwc_display_[disp_id]->GetClientTarget(
755                                  target, acquire_fence, dataspace, damage);
756   hwc_session_->hwc_display_[dummy_disp_id]->SetClientTarget(
757                                        target, acquire_fence, dataspace, damage);
758 
759 
760 
761   hwc_session_->hwc_display_[disp_id]->GetDisplayVsyncPeriod(&vsync_period);
762   hwc_session_->hwc_display_[dummy_disp_id]->SetDisplayVsyncPeriod(vsync_period);
763 
764   hwc_session_->locker_[dummy_disp_id].Unlock();  // Release the dummy display.
765   // Release the display's power-state transition var read lock.
766   hwc_session_->power_state_[disp_id].Unlock();
767 
768   // From now, till power-state transition ends, for operations that need to be non-blocking, do
769   // those operations on the dummy display.
770 
771   // Perform the actual [synchronous] power-state change.
772   hwc_session_->hwc_display_[disp_id]->SetPowerMode(mode, false /* teardown */);
773 
774   // Power state transition end.
775   // Acquire the display's power-state transition var read lock.
776   hwc_session_->power_state_[disp_id].Lock();
777   hwc_session_->power_state_transition_[disp_id] = false;
778   hwc_session_->locker_[dummy_disp_id].Lock();  // Lock the dummy display.
779 
780   // Retrieve the real display's layer-stack from the dummy display.
781   hwc_session_->hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
782   hwc_session_->hwc_display_[disp_id]->SetLayerStack(&stack);
783   bool vsync_pending = hwc_session_->hwc_display_[dummy_disp_id]->VsyncEnablePending();
784   if (vsync_pending) {
785     hwc_session_->hwc_display_[disp_id]->SetVsyncEnabled(HWC2::Vsync::Enable);
786   }
787   hwc_session_->hwc_display_[dummy_disp_id]->GetClientTarget(
788                                        target, acquire_fence, dataspace, damage);
789   hwc_session_->hwc_display_[disp_id]->SetClientTarget(
790                                  target, acquire_fence, dataspace, damage);
791 
792   // Read display has got layerstack. Update the fences.
793   hwc_session_->hwc_display_[disp_id]->PostPowerMode();
794 
795   hwc_session_->locker_[dummy_disp_id].Unlock();  // Release the dummy display.
796   hwc_session_->locker_[disp_id].Unlock();        // Release the real display.
797   // Release the display's power-state transition var read lock.
798   hwc_session_->power_state_[disp_id].Unlock();
799 
800   HWC2::PowerMode new_mode = hwc_session_->hwc_display_[disp_id]->GetCurrentPowerMode();
801   if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays &&
802       hwc_session_->hwc_display_[disp_id]->IsFirstCommitDone() &&
803       WaitForResourceNeeded(previous_mode, new_mode)) {
804     hwc_session_->WaitForResources(true, active_builtin_disp_id, disp_id);
805   }
806 
807   return 0;
808 }
809 
IsHDRSupported(uint32_t disp_id,bool * supported)810 int HWCSession::DisplayConfigImpl::IsHDRSupported(uint32_t disp_id, bool *supported) {
811   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
812     DLOGE("Not valid display");
813     return -EINVAL;
814   }
815   SCOPE_LOCK(hwc_session_->hdr_locker_[disp_id]);
816 
817   if (hwc_session_->is_hdr_display_.size() <= disp_id) {
818     DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
819           disp_id);
820     *supported = false;
821     return 0;
822   }
823 
824   *supported = static_cast<bool>(hwc_session_->is_hdr_display_[disp_id]);
825   return 0;
826 }
827 
IsWCGSupported(uint32_t disp_id,bool * supported)828 int HWCSession::DisplayConfigImpl::IsWCGSupported(uint32_t disp_id, bool *supported) {
829   // todo(user): Query wcg from sdm. For now assume them same.
830   return IsHDRSupported(disp_id, supported);
831 }
832 
SetLayerAsMask(uint32_t disp_id,uint64_t layer_id)833 int HWCSession::DisplayConfigImpl::SetLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
834   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
835     DLOGE("Not valid display");
836     return -EINVAL;
837   }
838   SCOPE_LOCK(hwc_session_->locker_[disp_id]);
839   HWCDisplay *hwc_display = hwc_session_->hwc_display_[disp_id];
840   if (!hwc_display) {
841     DLOGW("Display = %d is not connected.", disp_id);
842     return -EINVAL;
843   }
844 
845   if (hwc_session_->disable_mask_layer_hint_) {
846     DLOGW("Mask layer hint is disabled!");
847     return -EINVAL;
848   }
849 
850   auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
851   if (hwc_layer == nullptr) {
852     return -EINVAL;
853   }
854 
855   hwc_layer->SetLayerAsMask();
856 
857   return 0;
858 }
859 
GetDebugProperty(const std::string prop_name,std::string * value)860 int HWCSession::DisplayConfigImpl::GetDebugProperty(const std::string prop_name,
861                                                     std::string *value) {
862   std::string vendor_prop_name = DISP_PROP_PREFIX;
863   int error = -EINVAL;
864   char val[64] = {};
865 
866   vendor_prop_name += prop_name.c_str();
867   if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), val) == kErrorNone) {
868     *value = val;
869     error = 0;
870   }
871 
872   return error;
873 }
874 
GetActiveBuiltinDisplayAttributes(DisplayConfig::Attributes * attr)875 int HWCSession::DisplayConfigImpl::GetActiveBuiltinDisplayAttributes(
876                                                     DisplayConfig::Attributes *attr) {
877   int error = -EINVAL;
878   hwc2_display_t disp_id = hwc_session_->GetActiveBuiltinDisplay();
879 
880   if (disp_id >= HWCCallbacks::kNumDisplays) {
881     DLOGE("Invalid display = %d", UINT32(disp_id));
882   } else {
883     if (hwc_session_->hwc_display_[disp_id]) {
884       uint32_t config_index = 0;
885       HWC2::Error ret = hwc_session_->hwc_display_[disp_id]->GetActiveConfig(&config_index);
886       if (ret != HWC2::Error::None) {
887         goto err;
888       }
889       DisplayConfigVariableInfo var_info;
890       error = hwc_session_->hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index),
891                                                                                  &var_info);
892       if (!error) {
893         attr->vsync_period = var_info.vsync_period_ns;
894         attr->x_res = var_info.x_pixels;
895         attr->y_res = var_info.y_pixels;
896         attr->x_dpi = var_info.x_dpi;
897         attr->y_dpi = var_info.y_dpi;
898         attr->panel_type = DisplayConfig::DisplayPortType::kDefault;
899         attr->is_yuv = var_info.is_yuv;
900       }
901     }
902   }
903 
904 err:
905   return error;
906 }
907 
SetPanelLuminanceAttributes(uint32_t disp_id,float pan_min_lum,float pan_max_lum)908 int HWCSession::DisplayConfigImpl::SetPanelLuminanceAttributes(uint32_t disp_id, float pan_min_lum,
909                                                                float pan_max_lum) {
910   // currently doing only for virtual display
911   if (disp_id != qdutils::DISPLAY_VIRTUAL) {
912     return -EINVAL;
913   }
914 
915   // check for out of range luminance values
916   if (pan_min_lum <= 0.0f || pan_min_lum >= 1.0f ||
917       pan_max_lum <= 100.0f || pan_max_lum >= 1000.0f) {
918     return -EINVAL;
919   }
920 
921   std::lock_guard<std::mutex> obj(hwc_session_->mutex_lum_);
922   hwc_session_->set_min_lum_ = pan_min_lum;
923   hwc_session_->set_max_lum_ = pan_max_lum;
924   DLOGI("set max_lum %f, min_lum %f", pan_max_lum, pan_min_lum);
925 
926   return 0;
927 }
928 
IsBuiltInDisplay(uint32_t disp_id,bool * is_builtin)929 int HWCSession::DisplayConfigImpl::IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin) {
930   if ((hwc_session_->map_info_primary_.client_id == disp_id) &&
931       (hwc_session_->map_info_primary_.disp_type == kBuiltIn)) {
932     *is_builtin = true;
933     return 0;
934   }
935 
936   for (auto &info : hwc_session_->map_info_builtin_) {
937     if (disp_id == info.client_id) {
938       *is_builtin = true;
939       return 0;
940     }
941   }
942 
943   *is_builtin = false;
944   return 0;
945 }
946 
GetSupportedDSIBitClks(uint32_t disp_id,std::vector<uint64_t> * bit_clks)947 int HWCSession::DisplayConfigImpl::GetSupportedDSIBitClks(uint32_t disp_id,
948                                                           std::vector<uint64_t> *bit_clks) {
949   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
950     DLOGE("Not valid display");
951     return -EINVAL;
952   }
953   SCOPE_LOCK(hwc_session_->locker_[disp_id]);
954   if (!hwc_session_->hwc_display_[disp_id]) {
955     return -EINVAL;
956   }
957 
958   hwc_session_->hwc_display_[disp_id]->GetSupportedDSIClock(bit_clks);
959   return 0;
960 }
961 
GetDSIClk(uint32_t disp_id,uint64_t * bit_clk)962 int HWCSession::DisplayConfigImpl::GetDSIClk(uint32_t disp_id, uint64_t *bit_clk) {
963   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
964     DLOGE("Not valid display");
965     return -EINVAL;
966   }
967   SCOPE_LOCK(hwc_session_->locker_[disp_id]);
968   if (!hwc_session_->hwc_display_[disp_id]) {
969     return -EINVAL;
970   }
971 
972   hwc_session_->hwc_display_[disp_id]->GetDynamicDSIClock(bit_clk);
973 
974   return 0;
975 }
976 
SetDSIClk(uint32_t disp_id,uint64_t bit_clk)977 int HWCSession::DisplayConfigImpl::SetDSIClk(uint32_t disp_id, uint64_t bit_clk) {
978   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
979     DLOGE("Not valid display");
980     return -EINVAL;
981   }
982   SCOPE_LOCK(hwc_session_->locker_[disp_id]);
983   if (!hwc_session_->hwc_display_[disp_id]) {
984     return -1;
985   }
986 
987   return hwc_session_->hwc_display_[disp_id]->SetDynamicDSIClock(bit_clk);
988 }
989 
SetCWBOutputBuffer(uint32_t disp_id,const DisplayConfig::Rect rect,bool post_processed,const native_handle_t * buffer)990 int HWCSession::DisplayConfigImpl::SetCWBOutputBuffer(uint32_t disp_id,
991                                                       const DisplayConfig::Rect rect,
992                                                       bool post_processed,
993                                                       const native_handle_t *buffer) {
994   if (!callback_.lock() || !buffer) {
995     DLOGE("Invalid parameters");
996     return -1;
997   }
998 
999   if (disp_id != UINT32(DisplayConfig::DisplayType::kPrimary)) {
1000     DLOGE("Only supported for primary display at present.");
1001     return -1;
1002   }
1003 
1004   if (rect.left || rect.top || rect.right || rect.bottom) {
1005     DLOGE("Cropping rectangle is not supported.");
1006     return -1;
1007   }
1008 
1009   // Output buffer dump is not supported, if External or Virtual display is present.
1010   int external_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_EXTERNAL);
1011   int virtual_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_VIRTUAL);
1012   int primary_dpy_index = hwc_session_->GetDisplayIndex(qdutils::DISPLAY_PRIMARY);
1013 
1014   if (((external_dpy_index != -1) && hwc_session_->hwc_display_[external_dpy_index]) ||
1015       ((virtual_dpy_index != -1) && hwc_session_->hwc_display_[virtual_dpy_index])) {
1016     DLOGW("Output buffer dump is not supported with External or Virtual display!");
1017     return -1;
1018   }
1019 
1020   // Mutex scope
1021   {
1022     SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
1023     if (!hwc_session_->hwc_display_[primary_dpy_index]) {
1024       DLOGE("Display is not created yet.");
1025       return -1;
1026     }
1027   }
1028 
1029   return hwc_session_->cwb_.PostBuffer(callback_, post_processed,
1030                                        native_handle_clone(buffer));
1031 }
1032 
PostBuffer(std::weak_ptr<DisplayConfig::ConfigCallback> callback,bool post_processed,const native_handle_t * buffer)1033 int32_t HWCSession::CWB::PostBuffer(std::weak_ptr<DisplayConfig::ConfigCallback> callback,
1034                                     bool post_processed, const native_handle_t *buffer) {
1035   SCOPE_LOCK(queue_lock_);
1036 
1037   // Ensure that async task runs only until all queued CWB requests have been fulfilled.
1038   // If cwb queue is empty, async task has not either started or async task has finished
1039   // processing previously queued cwb requests. Start new async task on such a case as
1040   // currently running async task will automatically desolve without processing more requests.
1041   bool post_future = !queue_.size();
1042 
1043   QueueNode *node = new QueueNode(callback, post_processed, buffer);
1044   queue_.push(node);
1045 
1046   if (post_future) {
1047     // No need to do future.get() here for previously running async task. Async method will
1048     // guarantee to exit after cwb for all queued requests is indeed complete i.e. the respective
1049     // fences have signaled and client is notified through registered callbacks. This will make
1050     // sure that the new async task does not concurrently work with previous task. Let async running
1051     // thread dissolve on its own.
1052     future_ = std::async(HWCSession::CWB::AsyncTask, this);
1053   }
1054 
1055   return 0;
1056 }
1057 
ProcessRequests()1058 void HWCSession::CWB::ProcessRequests() {
1059   HWCDisplay *hwc_display = hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY];
1060   Locker &locker = hwc_session_->locker_[HWC_DISPLAY_PRIMARY];
1061 
1062   while (true) {
1063     QueueNode *node = nullptr;
1064     int status = 0;
1065 
1066     // Mutex scope
1067     // Just check if there is a next cwb request queued, exit the thread if nothing is pending.
1068     // Do not keep mutex locked so that client can freely queue more jobs to the current thread.
1069     {
1070       SCOPE_LOCK(queue_lock_);
1071       if (!queue_.size()) {
1072         break;
1073       }
1074 
1075       node = queue_.front();
1076     }
1077 
1078     // Configure cwb parameters, trigger refresh, wait for commit, get the release fence and
1079     // wait for fence to signal.
1080 
1081     // Mutex scope
1082     // Wait for previous commit to finish before configuring next buffer.
1083     {
1084       SEQUENCE_WAIT_SCOPE_LOCK(locker);
1085       if (hwc_display->SetReadbackBuffer(node->buffer, nullptr, node->post_processed,
1086                                          kCWBClientExternal) != HWC2::Error::None) {
1087         DLOGE("CWB buffer could not be set.");
1088         status = -1;
1089       }
1090     }
1091 
1092     if (!status) {
1093       hwc_session_->callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
1094 
1095       std::unique_lock<std::mutex> lock(mutex_);
1096       cv_.wait(lock);
1097 
1098       shared_ptr<Fence> release_fence = nullptr;
1099       // Mutex scope
1100       {
1101         SCOPE_LOCK(locker);
1102         hwc_display->GetReadbackBufferFence(&release_fence);
1103       }
1104 
1105       if (release_fence >= 0) {
1106         status = Fence::Wait(release_fence);
1107       } else {
1108         DLOGE("CWB release fence could not be retrieved.");
1109         status = -1;
1110       }
1111     }
1112 
1113     // Notify client about buffer status and erase the node from pending request queue.
1114     std::shared_ptr<DisplayConfig::ConfigCallback> callback = node->callback.lock();
1115     if (callback) {
1116       callback->NotifyCWBBufferDone(status, node->buffer);
1117     }
1118 
1119     native_handle_close(node->buffer);
1120     native_handle_delete(const_cast<native_handle_t *>(node->buffer));
1121     delete node;
1122 
1123     // Mutex scope
1124     // Make sure to exit here, if queue becomes empty after erasing current node from queue,
1125     // so that the current async task does not operate concurrently with a new future task.
1126     {
1127       SCOPE_LOCK(queue_lock_);
1128       queue_.pop();
1129 
1130       if (!queue_.size()) {
1131         break;
1132       }
1133     }
1134   }
1135 }
1136 
AsyncTask(CWB * cwb)1137 void HWCSession::CWB::AsyncTask(CWB *cwb) {
1138   cwb->ProcessRequests();
1139 }
1140 
PresentDisplayDone(hwc2_display_t disp_id)1141 void HWCSession::CWB::PresentDisplayDone(hwc2_display_t disp_id) {
1142   if (disp_id != HWC_DISPLAY_PRIMARY) {
1143     return;
1144   }
1145 
1146   std::unique_lock<std::mutex> lock(mutex_);
1147   cv_.notify_one();
1148 }
1149 
SetQsyncMode(uint32_t disp_id,DisplayConfig::QsyncMode mode)1150 int HWCSession::DisplayConfigImpl::SetQsyncMode(uint32_t disp_id, DisplayConfig::QsyncMode mode) {
1151   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
1152     DLOGE("Not valid display");
1153     return -EINVAL;
1154   }
1155   SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[disp_id]);
1156   if (!hwc_session_->hwc_display_[disp_id]) {
1157     return -1;
1158   }
1159 
1160   QSyncMode qsync_mode = kQSyncModeNone;
1161   switch (mode) {
1162     case DisplayConfig::QsyncMode::kNone:
1163       qsync_mode = kQSyncModeNone;
1164       break;
1165     case DisplayConfig::QsyncMode::kWaitForFencesOneFrame:
1166       qsync_mode = kQsyncModeOneShot;
1167       break;
1168     case DisplayConfig::QsyncMode::kWaitForFencesEachFrame:
1169       qsync_mode = kQsyncModeOneShotContinuous;
1170       break;
1171     case DisplayConfig::QsyncMode::kWaitForCommitEachFrame:
1172       qsync_mode = kQSyncModeContinuous;
1173       break;
1174   }
1175 
1176   hwc_session_->hwc_display_[disp_id]->SetQSyncMode(qsync_mode);
1177   return 0;
1178 }
1179 
IsSmartPanelConfig(uint32_t disp_id,uint32_t config_id,bool * is_smart)1180 int HWCSession::DisplayConfigImpl::IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id,
1181                                                       bool *is_smart) {
1182   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
1183     DLOGE("Not valid display");
1184     return -EINVAL;
1185   }
1186   SCOPE_LOCK(hwc_session_->locker_[disp_id]);
1187   if (!hwc_session_->hwc_display_[disp_id]) {
1188     DLOGE("Display %d is not created yet.", disp_id);
1189     *is_smart = false;
1190     return -EINVAL;
1191   }
1192 
1193   if (hwc_session_->hwc_display_[disp_id]->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) {
1194     return false;
1195   }
1196 
1197   *is_smart = hwc_session_->hwc_display_[disp_id]->IsSmartPanelConfig(config_id);
1198   return 0;
1199 }
1200 
IsAsyncVDSCreationSupported(bool * supported)1201 int HWCSession::DisplayConfigImpl::IsAsyncVDSCreationSupported(bool *supported) {
1202   if (!hwc_session_->async_vds_creation_) {
1203     *supported = false;
1204     return 0;
1205   }
1206 
1207   *supported = true;
1208   return 0;
1209 }
1210 
CreateVirtualDisplay(uint32_t width,uint32_t height,int32_t format)1211 int HWCSession::DisplayConfigImpl::CreateVirtualDisplay(uint32_t width, uint32_t height,
1212                                                         int32_t format) {
1213   if (!hwc_session_->async_vds_creation_) {
1214     return HWC2_ERROR_UNSUPPORTED;
1215   }
1216 
1217   if (!width || !height) {
1218     return HWC2_ERROR_BAD_PARAMETER;
1219   }
1220 
1221   hwc2_display_t active_builtin_disp_id = hwc_session_->GetActiveBuiltinDisplay();
1222   auto status = hwc_session_->CreateVirtualDisplayObj(width, height, &format,
1223                                                       &hwc_session_->virtual_id_);
1224   if (status == HWC2::Error::None) {
1225     DLOGI("Created virtual display id:%" PRIu64 ", res: %dx%d",
1226           hwc_session_->virtual_id_, width, height);
1227     if (active_builtin_disp_id < HWCCallbacks::kNumRealDisplays) {
1228       hwc_session_->WaitForResources(true, active_builtin_disp_id, hwc_session_->virtual_id_);
1229     }
1230   } else {
1231     DLOGE("Failed to create virtual display: %s", to_string(status).c_str());
1232   }
1233 
1234   return INT(status);
1235 }
1236 
IsRotatorSupportedFormat(int hal_format,bool ubwc,bool * supported)1237 int HWCSession::DisplayConfigImpl::IsRotatorSupportedFormat(int hal_format, bool ubwc,
1238                                                              bool *supported) {
1239   if (!hwc_session_->core_intf_) {
1240     DLOGW("core_intf_ not initialized.");
1241     *supported = false;
1242     return -EINVAL;
1243   }
1244   int flag = ubwc ? private_handle_t::PRIV_FLAGS_UBWC_ALIGNED : 0;
1245 
1246   LayerBufferFormat sdm_format = HWCLayer::GetSDMFormat(hal_format, flag);
1247 
1248   *supported = hwc_session_->core_intf_->IsRotatorSupportedFormat(sdm_format);
1249   return 0;
1250 }
1251 
ControlQsyncCallback(bool enable)1252 int HWCSession::DisplayConfigImpl::ControlQsyncCallback(bool enable) {
1253   if (enable) {
1254     hwc_session_->qsync_callback_ = callback_;
1255   } else {
1256     hwc_session_->qsync_callback_.reset();
1257   }
1258 
1259   return 0;
1260 }
1261 
ControlIdleStatusCallback(bool enable)1262 int HWCSession::DisplayConfigImpl::ControlIdleStatusCallback(bool enable) {
1263   if (enable) {
1264     hwc_session_->idle_callback_ = callback_;
1265   } else {
1266     hwc_session_->idle_callback_.reset();
1267   }
1268 
1269   return 0;
1270 }
1271 
IsRCSupported(uint32_t disp_id,bool * supported)1272 int HWCSession::DisplayConfigImpl::IsRCSupported(uint32_t disp_id, bool *supported) {
1273   // Mask layers can potentially be shown on any display so report RC supported on all displays if
1274   // the property enables the feature for use.
1275   int val = false;  // Default value.
1276   Debug::GetProperty(ENABLE_ROUNDED_CORNER, &val);
1277   *supported = val ? true: false;
1278 
1279   return 0;
1280 }
1281 
AllowIdleFallback()1282 int HWCSession::DisplayConfigImpl::AllowIdleFallback() {
1283   SEQUENCE_WAIT_SCOPE_LOCK(hwc_session_->locker_[HWC_DISPLAY_PRIMARY]);
1284 
1285   uint32_t active_ms = 0;
1286   uint32_t inactive_ms = 0;
1287   Debug::GetIdleTimeoutMs(&active_ms, &inactive_ms);
1288   if (hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]) {
1289     DLOGI("enable idle time active_ms:%d inactive_ms:%d",active_ms,inactive_ms);
1290     hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(active_ms, inactive_ms);
1291     hwc_session_->is_idle_time_up_ = true;
1292     return 0;
1293   }
1294 
1295   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
1296   return -ENODEV;
1297 }
1298 
1299 }  // namespace sdm
1300