1 /*
2 * Copyright (c) 2017-2020, 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 <sync/sync.h>
33 #include <vector>
34 #include <string>
35 
36 #include "hwc_buffer_sync_handler.h"
37 #include "hwc_session.h"
38 #include "hwc_debugger.h"
39 
40 #define __CLASS__ "HWCSession"
41 
42 namespace sdm {
43 
44 using ::android::hardware::Void;
45 
StartServices()46 void HWCSession::StartServices() {
47   android::status_t status = IDisplayConfig::registerAsService();
48   if (status != android::OK) {
49     DLOGW("Could not register IDisplayConfig as service (%d).", status);
50   } else {
51     DLOGI("IDisplayConfig service registration completed.");
52   }
53 }
54 
MapDisplayType(IDisplayConfig::DisplayType dpy)55 int MapDisplayType(IDisplayConfig::DisplayType dpy) {
56   switch (dpy) {
57     case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
58       return qdutils::DISPLAY_PRIMARY;
59 
60     case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
61       return qdutils::DISPLAY_EXTERNAL;
62 
63     case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
64       return qdutils::DISPLAY_VIRTUAL;
65 
66     default:
67       break;
68   }
69 
70   return -EINVAL;
71 }
72 
MapExternalStatus(IDisplayConfig::DisplayExternalStatus status)73 HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) {
74   switch (status) {
75     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE:
76       return HWCDisplay::kDisplayStatusOffline;
77 
78     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE:
79       return HWCDisplay::kDisplayStatusOnline;
80 
81     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE:
82       return HWCDisplay::kDisplayStatusPause;
83 
84     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME:
85       return HWCDisplay::kDisplayStatusResume;
86 
87     default:
88       break;
89   }
90 
91   return HWCDisplay::kDisplayStatusInvalid;
92 }
93 
94 // Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
isDisplayConnected(IDisplayConfig::DisplayType dpy,isDisplayConnected_cb _hidl_cb)95 Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
96                                             isDisplayConnected_cb _hidl_cb) {
97   int32_t error = -EINVAL;
98   bool connected = false;
99   int disp_id = MapDisplayType(dpy);
100   int disp_idx = GetDisplayIndex(disp_id);
101 
102   if (disp_idx == -1) {
103     DLOGE("Invalid display = %d", disp_id);
104   } else {
105     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
106     connected = hwc_display_[disp_idx];
107     error = 0;
108   }
109   _hidl_cb(error, connected);
110 
111   return Void();
112 }
113 
SetSecondaryDisplayStatus(int disp_id,HWCDisplay::DisplayStatus status)114 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
115   int disp_idx = GetDisplayIndex(disp_id);
116   int err = -EINVAL;
117   if (disp_idx == -1) {
118     DLOGE("Invalid display = %d", disp_id);
119     return -EINVAL;
120   }
121 
122   if (disp_idx == qdutils::DISPLAY_PRIMARY) {
123     DLOGE("Not supported for this display");
124     return err;
125   }
126 
127   {
128     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
129     if (!hwc_display_[disp_idx]) {
130       DLOGW("Display is not connected");
131       return err;
132     }
133     DLOGI("Display = %d, Status = %d", disp_idx, status);
134     err = hwc_display_[disp_idx]->SetDisplayStatus(status);
135     if (err != 0) {
136       return err;
137     }
138   }
139 
140   if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
141     hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
142     if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
143       {
144         SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
145         hwc_display_[active_builtin_disp_id]->ResetValidation();
146       }
147       callbacks_.Refresh(active_builtin_disp_id);
148     }
149   }
150 
151   return err;
152 }
153 
setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,IDisplayConfig::DisplayExternalStatus status)154 Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
155                                                   IDisplayConfig::DisplayExternalStatus status) {
156   return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
157 }
158 
configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,uint32_t refreshRate)159 Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
160                                                    uint32_t refreshRate) {
161   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
162   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
163 
164   if (!hwc_display) {
165     DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
166     return -EINVAL;
167   }
168 
169   switch (op) {
170     case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
171       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
172 
173     case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
174       return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
175 
176     case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
177       return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
178 
179     default:
180       DLOGW("Invalid operation %d", op);
181       return -EINVAL;
182   }
183 
184   return 0;
185 }
186 
GetConfigCount(int disp_id,uint32_t * count)187 int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
188   int disp_idx = GetDisplayIndex(disp_id);
189   if (disp_idx == -1) {
190     DLOGE("Invalid display = %d", disp_id);
191     return -EINVAL;
192   }
193 
194   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
195 
196   if (hwc_display_[disp_idx]) {
197     return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
198   }
199 
200   return -EINVAL;
201 }
202 
getConfigCount(IDisplayConfig::DisplayType dpy,getConfigCount_cb _hidl_cb)203 Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
204                                         getConfigCount_cb _hidl_cb) {
205   uint32_t count = 0;
206   int32_t error = GetConfigCount(MapDisplayType(dpy), &count);
207 
208   _hidl_cb(error, count);
209 
210   return Void();
211 }
212 
GetActiveConfigIndex(int disp_id,uint32_t * config)213 int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
214   int disp_idx = GetDisplayIndex(disp_id);
215   if (disp_idx == -1) {
216     DLOGE("Invalid display = %d", disp_id);
217     return -EINVAL;
218   }
219 
220   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
221 
222   if (hwc_display_[disp_idx]) {
223     return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
224   }
225 
226   return -EINVAL;
227 }
228 
getActiveConfig(IDisplayConfig::DisplayType dpy,getActiveConfig_cb _hidl_cb)229 Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
230                                          getActiveConfig_cb _hidl_cb) {
231   uint32_t config = 0;
232   int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config);
233 
234   _hidl_cb(error, config);
235 
236   return Void();
237 }
238 
SetActiveConfigIndex(int disp_id,uint32_t config)239 int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
240   int disp_idx = GetDisplayIndex(disp_id);
241   if (disp_idx == -1) {
242     DLOGE("Invalid display = %d", disp_id);
243     return -EINVAL;
244   }
245 
246   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
247   int32_t error = -EINVAL;
248   if (hwc_display_[disp_idx]) {
249     error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
250     if (!error) {
251       Refresh(0);
252     }
253   }
254 
255   return error;
256 }
257 
setActiveConfig(IDisplayConfig::DisplayType dpy,uint32_t config)258 Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
259   return SetActiveConfigIndex(MapDisplayType(dpy), config);
260 }
261 
getDisplayAttributes(uint32_t configIndex,IDisplayConfig::DisplayType dpy,getDisplayAttributes_cb _hidl_cb)262 Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
263                                               IDisplayConfig::DisplayType dpy,
264                                               getDisplayAttributes_cb _hidl_cb) {
265   int32_t error = -EINVAL;
266   IDisplayConfig::DisplayAttributes display_attributes = {};
267   int disp_id = MapDisplayType(dpy);
268   int disp_idx = GetDisplayIndex(disp_id);
269 
270   if (disp_idx == -1) {
271     DLOGE("Invalid display = %d", disp_id);
272   } else {
273     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
274     if (hwc_display_[disp_idx]) {
275       DisplayConfigVariableInfo var_info;
276       error = hwc_display_[disp_idx]->GetDisplayAttributesForConfig(INT(configIndex), &var_info);
277       if (!error) {
278         display_attributes.vsyncPeriod = var_info.vsync_period_ns;
279         display_attributes.xRes = var_info.x_pixels;
280         display_attributes.yRes = var_info.y_pixels;
281         display_attributes.xDpi = var_info.x_dpi;
282         display_attributes.yDpi = var_info.y_dpi;
283         display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
284         display_attributes.isYuv = var_info.is_yuv;
285       }
286     }
287   }
288   _hidl_cb(error, display_attributes);
289 
290   return Void();
291 }
292 
setPanelBrightness(uint32_t level)293 Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
294   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
295   int32_t error = -EINVAL;
296 
297   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
298     error = INT32(hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT32(level)));
299     if (error) {
300       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
301     }
302   }
303 
304   return error;
305 }
306 
GetPanelBrightness(int32_t & level) const307 int32_t HWCSession::GetPanelBrightness(int32_t &level) const {
308   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
309   int32_t error = -EINVAL;
310 
311   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
312     error = INT32(hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level));
313     if (error) {
314       DLOGE("Failed to get the panel brightness. Error = %d", error);
315     }
316   }
317 
318   return error;
319 }
320 
GetPanelMaxBrightness(int32_t & max_brightness_level) const321 int32_t HWCSession::GetPanelMaxBrightness(int32_t &max_brightness_level) const {
322   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
323   int32_t error = -EINVAL;
324 
325   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
326     error = INT32(hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelMaxBrightness(max_brightness_level));
327     if (error) {
328       DLOGE("Failed to get the panel max brightness. Error = %d", error);
329     }
330   }
331 
332   return error;
333 }
334 
getPanelBrightness(getPanelBrightness_cb _hidl_cb)335 Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
336   int32_t level = 0;
337   int32_t error = GetPanelBrightness(level);
338 
339   _hidl_cb(error, static_cast<uint32_t>(level));
340 
341   return Void();
342 }
343 
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)344 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
345   DLOGI("Display %d", disp_id);
346 
347   int disp_idx = GetDisplayIndex(disp_id);
348   if (disp_idx == -1) {
349     DLOGE("Invalid display = %d", disp_id);
350     return -EINVAL;
351   }
352 
353   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
354   if (disp_idx != HWC_DISPLAY_EXTERNAL) {
355     DLOGE("Not supported for display");
356   } else if (!hwc_display_[disp_idx]) {
357     DLOGW("Display is not connected");
358   } else {
359     return hwc_display_[disp_idx]->OnMinHdcpEncryptionLevelChange(min_enc_level);
360   }
361 
362   return -EINVAL;
363 }
364 
minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,uint32_t min_enc_level)365 Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
366                                                           uint32_t min_enc_level) {
367   return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
368 }
369 
refreshScreen()370 Return<int32_t> HWCSession::refreshScreen() {
371   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
372   Refresh(HWC_DISPLAY_PRIMARY);
373 
374   return 0;
375 }
376 
ControlPartialUpdate(int disp_id,bool enable)377 int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
378   int disp_idx = GetDisplayIndex(disp_id);
379   if (disp_idx == -1) {
380     DLOGE("Invalid display = %d", disp_id);
381     return -EINVAL;
382   }
383 
384   if (disp_idx != HWC_DISPLAY_PRIMARY) {
385     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
386     return -EINVAL;
387   }
388 
389   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
390   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
391   if (!hwc_display) {
392     DLOGE("primary display object is not instantiated");
393     return -EINVAL;
394   }
395 
396   uint32_t pending = 0;
397   DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
398 
399   if (hwc_error == kErrorNone) {
400     if (!pending) {
401       return 0;
402     }
403   } else if (hwc_error == kErrorNotSupported) {
404     return 0;
405   } else {
406     return -EINVAL;
407   }
408 
409   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
410   Refresh(HWC_DISPLAY_PRIMARY);
411 
412   // Wait until partial update control is complete
413   int32_t error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
414 
415   return error;
416 }
417 
controlPartialUpdate(IDisplayConfig::DisplayType dpy,bool enable)418 Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
419   return ControlPartialUpdate(MapDisplayType(dpy), enable);
420 }
421 
toggleScreenUpdate(bool on)422 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
423   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
424 
425   int32_t error = -EINVAL;
426   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
427     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
428     if (error) {
429       DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
430     }
431   }
432 
433   return error;
434 }
435 
setIdleTimeout(uint32_t value)436 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
437   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
438 
439   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
440     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
441     return 0;
442   }
443 
444   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
445   return -ENODEV;
446 }
447 
getHDRCapabilities(IDisplayConfig::DisplayType dpy,getHDRCapabilities_cb _hidl_cb)448 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
449                                             getHDRCapabilities_cb _hidl_cb) {
450   int32_t error = -EINVAL;
451   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
452 
453   do {
454     if (!_hidl_cb) {
455       DLOGE("_hidl_cb callback not provided.");
456       break;
457     }
458 
459     int disp_id = MapDisplayType(dpy);
460     int disp_idx = GetDisplayIndex(disp_id);
461     if (disp_idx == -1) {
462       DLOGE("Invalid display = %d", disp_id);
463       break;
464     }
465 
466     SCOPE_LOCK(locker_[disp_id]);
467     HWCDisplay *hwc_display = hwc_display_[disp_idx];
468     if (!hwc_display) {
469       DLOGW("Display = %d is not connected.", disp_idx);
470       error = -ENODEV;
471       break;
472     }
473 
474     // query number of hdr types
475     uint32_t out_num_types = 0;
476     float out_max_luminance = 0.0f;
477     float out_max_average_luminance = 0.0f;
478     float out_min_luminance = 0.0f;
479     if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
480                                         &out_max_average_luminance, &out_min_luminance)
481                                         != HWC2::Error::None) {
482       break;
483     }
484     if (!out_num_types) {
485       error = 0;
486       break;
487     }
488 
489     // query hdr caps
490     hdr_caps.supportedHdrTypes.resize(out_num_types);
491 
492     if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
493                                         &out_max_luminance, &out_max_average_luminance,
494                                         &out_min_luminance) == HWC2::Error::None) {
495       error = 0;
496     }
497   } while (false);
498 
499   _hidl_cb(error, hdr_caps);
500 
501   return Void();
502 }
503 
setCameraLaunchStatus(uint32_t on)504 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
505   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
506   if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
507     DLOGE("No active displays");
508     return -EINVAL;
509   }
510   SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
511 
512   if (null_display_mode_) {
513     return 0;
514   }
515 
516   if (!core_intf_) {
517     DLOGW("core_intf_ not initialized.");
518     return -ENOENT;
519   }
520 
521   if (!hwc_display_[active_builtin_disp_id]) {
522     DLOGW("Display = %d is not connected.", active_builtin_disp_id);
523     return -ENODEV;
524   }
525 
526   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
527 
528   // trigger invalidate to apply new bw caps.
529   Refresh(active_builtin_disp_id);
530 
531   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
532     return -EINVAL;
533   }
534 
535   new_bw_mode_ = true;
536   need_invalidate_ = true;
537   hwc_display_[active_builtin_disp_id]->ResetValidation();
538 
539   return 0;
540 }
541 
DisplayBWTransactionPending(bool * status)542 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
543   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
544 
545   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
546     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
547       DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
548       *status = false;
549     }
550 
551     return 0;
552   }
553 
554   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
555   return -ENODEV;
556 }
557 
displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb)558 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
559   bool status = true;
560 
561   if (!_hidl_cb) {
562       DLOGE("_hidl_cb callback not provided.");
563       return Void();
564   }
565 
566   int32_t error = DisplayBWTransactionPending(&status);
567 
568   _hidl_cb(error, status);
569 
570   return Void();
571 }
572 
setDisplayAnimating(uint64_t display_id,bool animating)573 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
574   return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
575                              &HWCDisplay::SetDisplayAnimating, animating);
576 }
577 
setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,uint32_t base,uint32_t count)578 Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
579                                             uint32_t base, uint32_t count) {
580   return -1;
581 }
582 
controlIdlePowerCollapse(bool enable,bool synchronous)583 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
584   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
585   if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
586     DLOGE("No active displays");
587     return -EINVAL;
588   }
589   SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
590 
591   if (hwc_display_[active_builtin_disp_id]) {
592     if (!enable) {
593       if (!idle_pc_ref_cnt_) {
594         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
595                                                                                   synchronous);
596         if (err != kErrorNone) {
597           return (err == kErrorNotSupported) ? 0 : -EINVAL;
598         }
599         Refresh(active_builtin_disp_id);
600         int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
601         if (error == ETIMEDOUT) {
602           DLOGE("Timed out!! Next frame commit done event not received!!");
603           return error;
604         }
605         DLOGI("Idle PC disabled!!");
606       }
607       idle_pc_ref_cnt_++;
608     } else if (idle_pc_ref_cnt_ > 0) {
609       if (!(idle_pc_ref_cnt_ - 1)) {
610         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
611                                                                                   synchronous);
612         if (err != kErrorNone) {
613           return (err == kErrorNotSupported) ? 0 : -EINVAL;
614         }
615         DLOGI("Idle PC enabled!!");
616       }
617       idle_pc_ref_cnt_--;
618     }
619     return 0;
620   }
621 
622   DLOGW("Display = %d is not connected.", active_builtin_disp_id);
623   return -ENODEV;
624 }
625 
IsWbUbwcSupported(int * value)626 int32_t HWCSession::IsWbUbwcSupported(int *value) {
627   HWDisplaysInfo hw_displays_info = {};
628   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
629   if (error != kErrorNone) {
630     return -EINVAL;
631   }
632 
633   for (auto &iter : hw_displays_info) {
634     auto &info = iter.second;
635     if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
636       *value = 1;
637     }
638   }
639 
640   return error;
641 }
642 
getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb)643 Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
644   int value = 0;
645   IDisplayConfig::WriteBackCapabilities wb_caps = {};
646   int32_t error = IsWbUbwcSupported(&value);
647   wb_caps.isWbUbwcSupported = value;
648   _hidl_cb(error, wb_caps);
649 
650   return Void();
651 }
652 
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)653 Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
654                                                 uint32_t h_end, uint32_t v_start, uint32_t v_end,
655                                                 uint32_t factor_in, uint32_t factor_out) {
656   return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
657                              &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
658                              factor_in, factor_out);
659 }
660 
updateVSyncSourceOnPowerModeOff()661 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeOff() {
662   return 0;
663 }
664 
updateVSyncSourceOnPowerModeDoze()665 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeDoze() {
666   return 0;
667 }
668 
isPowerModeOverrideSupported(uint32_t disp_id)669 Return<bool> HWCSession::isPowerModeOverrideSupported(uint32_t disp_id) {
670   if (!async_powermode_ || (disp_id > HWCCallbacks::kNumRealDisplays)) {
671     return false;
672   }
673 
674   return true;
675 }
676 
setPowerMode(uint32_t disp_id,PowerMode power_mode)677 Return<int32_t> HWCSession::setPowerMode(uint32_t disp_id, PowerMode power_mode) {
678   SCOPE_LOCK(display_config_locker_);
679 
680   if (!isPowerModeOverrideSupported(disp_id)) {
681     return 0;
682   }
683 
684   DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
685   HWCDisplay::HWCLayerStack stack = {};
686   hwc2_display_t dummy_disp_id = map_hwc_display_.at(disp_id);
687 
688   {
689     // Power state transition start.
690     Locker::ScopeLock lock_power(power_state_[disp_id]);
691     Locker::ScopeLock lock_primary(locker_[disp_id]);
692     Locker::ScopeLock lock_dummy(locker_[dummy_disp_id]);
693 
694     power_state_transition_[disp_id] = true;
695     // Pass on the complete stack to dummy display.
696     hwc_display_[disp_id]->GetLayerStack(&stack);
697     // Update the same stack onto dummy display.
698     hwc_display_[dummy_disp_id]->SetLayerStack(&stack);
699   }
700 
701   {
702     SCOPE_LOCK(locker_[disp_id]);
703     auto mode = static_cast<HWC2::PowerMode>(power_mode);
704     hwc_display_[disp_id]->SetPowerMode(mode, false /* teardown */);
705   }
706 
707   {
708     // Power state transition end.
709     Locker::ScopeLock lock_power(power_state_[disp_id]);
710     Locker::ScopeLock lock_primary(locker_[disp_id]);
711     Locker::ScopeLock lock_dummy(locker_[dummy_disp_id]);
712     // Pass on the layer stack to real display.
713     hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
714     // Update the same stack onto real display.
715     hwc_display_[disp_id]->SetLayerStack(&stack);
716     // Read display has got layerstack. Update the fences.
717     hwc_display_[disp_id]->PostPowerMode();
718 
719     power_state_transition_[disp_id] = false;
720   }
721 
722   return 0;
723 }
724 
isHDRSupported(uint32_t disp_id)725 Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
726   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
727     DLOGE("Not valid display");
728     return false;
729   }
730   SCOPE_LOCK(locker_[disp_id]);
731 
732   if (is_hdr_display_.size() <= disp_id) {
733     DLOGW("is_hdr_display_ is not initialized for display %d!! Reporting it as HDR not supported",
734           disp_id);
735     return false;
736   }
737 
738   return static_cast<bool>(is_hdr_display_[disp_id]);
739 }
740 
isWCGSupported(uint32_t disp_id)741 Return<bool> HWCSession::isWCGSupported(uint32_t disp_id) {
742   // todo(user): Query wcg from sdm. For now assume them same.
743   return isHDRSupported(disp_id);
744 }
745 
setLayerAsMask(uint32_t disp_id,uint64_t layer_id)746 Return<int32_t> HWCSession::setLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
747   SCOPE_LOCK(locker_[disp_id]);
748   HWCDisplay *hwc_display = hwc_display_[disp_id];
749   if (!hwc_display) {
750     DLOGW("Display = %d is not connected.", disp_id);
751     return -EINVAL;
752   }
753 
754   if (disable_mask_layer_hint_) {
755     DLOGW("Mask layer hint is disabled!");
756     return -EINVAL;
757   }
758 
759   auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
760   if (hwc_layer == nullptr) {
761     return -EINVAL;
762   }
763 
764   hwc_layer->SetLayerAsMask();
765 
766   return 0;
767 }
768 
getDebugProperty(const hidl_string & prop_name,getDebugProperty_cb _hidl_cb)769 Return<void> HWCSession::getDebugProperty(const hidl_string &prop_name,
770                                           getDebugProperty_cb _hidl_cb) {
771   std::string vendor_prop_name = DISP_PROP_PREFIX;
772   char value[64] = {};
773   hidl_string result = "";
774   int32_t error = -EINVAL;
775 
776   vendor_prop_name += prop_name.c_str();
777   if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) == kErrorNone) {
778     result = value;
779     error = 0;
780   }
781 
782   _hidl_cb(result, error);
783 
784   return Void();
785 }
786 
getActiveBuiltinDisplayAttributes(getDisplayAttributes_cb _hidl_cb)787 Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
788                                           getDisplayAttributes_cb _hidl_cb) {
789   int32_t error = -EINVAL;
790   IDisplayConfig::DisplayAttributes display_attributes = {};
791   hwc2_display_t disp_id = GetActiveBuiltinDisplay();
792 
793   if (disp_id >= HWCCallbacks::kNumDisplays) {
794     DLOGE("Invalid display = %d", disp_id);
795   } else {
796     if (hwc_display_[disp_id]) {
797       uint32_t config_index = 0;
798       HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
799       if (ret != HWC2::Error::None) {
800         goto err;
801       }
802       DisplayConfigVariableInfo var_info;
803       error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
804       if (!error) {
805         display_attributes.vsyncPeriod = var_info.vsync_period_ns;
806         display_attributes.xRes = var_info.x_pixels;
807         display_attributes.yRes = var_info.y_pixels;
808         display_attributes.xDpi = var_info.x_dpi;
809         display_attributes.yDpi = var_info.y_dpi;
810         display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
811         display_attributes.isYuv = var_info.is_yuv;
812       }
813     }
814   }
815 
816 err:
817   _hidl_cb(error, display_attributes);
818 
819   return Void();
820 }
821 
setPanelLuminanceAttributes(uint32_t disp_id,float pan_min_lum,float pan_max_lum)822 Return<int32_t> HWCSession::setPanelLuminanceAttributes(uint32_t disp_id, float pan_min_lum,
823                                                         float pan_max_lum) {
824   // currently doing only for virtual display
825   if (disp_id != qdutils::DISPLAY_VIRTUAL) {
826     return -EINVAL;
827   }
828 
829   std::lock_guard<std::mutex> obj(mutex_lum_);
830   set_min_lum_ = pan_min_lum;
831   set_max_lum_ = pan_max_lum;
832   DLOGI("set max_lum %f, min_lum %f", set_max_lum_, set_min_lum_);
833 
834   return 0;
835 }
836 
isBuiltInDisplay(uint32_t disp_id)837 Return<bool> HWCSession::isBuiltInDisplay(uint32_t disp_id) {
838   if ((map_info_primary_.client_id == disp_id) && (map_info_primary_.disp_type == kBuiltIn))
839     return true;
840 
841   for (auto &info : map_info_builtin_) {
842     if (disp_id == info.client_id) {
843       return true;
844     }
845   }
846 
847   return false;
848 }
849 
getSupportedDSIBitClks(uint32_t disp_id,getSupportedDSIBitClks_cb _hidl_cb)850 Return<void> HWCSession::getSupportedDSIBitClks(uint32_t disp_id,
851                                                 getSupportedDSIBitClks_cb _hidl_cb) {
852   SCOPE_LOCK(locker_[disp_id]);
853   if (!hwc_display_[disp_id]) {
854     return Void();
855   }
856 
857   std::vector<uint64_t> bit_clks;
858   hwc_display_[disp_id]->GetSupportedDSIClock(&bit_clks);
859 
860   hidl_vec<uint64_t> hidl_bit_clks = bit_clks;
861   _hidl_cb(hidl_bit_clks);
862 
863   return Void();
864 }
865 
getDSIClk(uint32_t disp_id)866 Return<uint64_t> HWCSession::getDSIClk(uint32_t disp_id) {
867   SCOPE_LOCK(locker_[disp_id]);
868   if (!hwc_display_[disp_id]) {
869     return 0;
870   }
871 
872   uint64_t bit_clk = 0;
873   hwc_display_[disp_id]->GetDynamicDSIClock(&bit_clk);
874 
875   return bit_clk;
876 }
877 
setDSIClk(uint32_t disp_id,uint64_t bit_clk)878 Return<int32_t> HWCSession::setDSIClk(uint32_t disp_id, uint64_t bit_clk) {
879   SCOPE_LOCK(locker_[disp_id]);
880   if (!hwc_display_[disp_id]) {
881     return -1;
882   }
883 
884   return hwc_display_[disp_id]->SetDynamicDSIClock(bit_clk);
885 }
886 
setCWBOutputBuffer(const::android::sp<IDisplayCWBCallback> & callback,uint32_t disp_id,const Rect & rect,bool post_processed,const hidl_handle & buffer)887 Return<int32_t> HWCSession::setCWBOutputBuffer(const ::android::sp<IDisplayCWBCallback> &callback,
888                                                uint32_t disp_id, const Rect &rect,
889                                                bool post_processed, const hidl_handle& buffer) {
890   return -1;
891 }
892 
setQsyncMode(uint32_t disp_id,IDisplayConfig::QsyncMode mode)893 Return<int32_t> HWCSession::setQsyncMode(uint32_t disp_id, IDisplayConfig::QsyncMode mode) {
894   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
895   if (!hwc_display_[disp_id]) {
896     return -1;
897   }
898 
899   QSyncMode qsync_mode = kQSyncModeNone;
900   switch (mode) {
901     case IDisplayConfig::QsyncMode::NONE:
902       qsync_mode = kQSyncModeNone;
903       break;
904     case IDisplayConfig::QsyncMode::WAIT_FOR_FENCES_ONE_FRAME:
905       qsync_mode = kQsyncModeOneShot;
906       break;
907     case IDisplayConfig::QsyncMode::WAIT_FOR_FENCES_EACH_FRAME:
908       qsync_mode = kQsyncModeOneShotContinuous;
909       break;
910     case IDisplayConfig::QsyncMode::WAIT_FOR_COMMIT_EACH_FRAME:
911       qsync_mode = kQSyncModeContinuous;
912       break;
913   }
914 
915   hwc_display_[disp_id]->SetQSyncMode(qsync_mode);
916   return 0;
917 }
918 
919 }  // namespace sdm
920