1 /*
2 * Copyright (c) 2017-2019, 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 = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(INT(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(int * level)307 int32_t HWCSession::GetPanelBrightness(int *level) {
308   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
309   int32_t error = -EINVAL;
310 
311   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
312     error = 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 
getPanelBrightness(getPanelBrightness_cb _hidl_cb)321 Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
322   int level = 0;
323   int32_t error = GetPanelBrightness(&level);
324 
325   _hidl_cb(error, static_cast<uint32_t>(level));
326 
327   return Void();
328 }
329 
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)330 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
331   DLOGI("Display %d", disp_id);
332 
333   int disp_idx = GetDisplayIndex(disp_id);
334   if (disp_idx == -1) {
335     DLOGE("Invalid display = %d", disp_id);
336     return -EINVAL;
337   }
338 
339   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
340   if (disp_idx != HWC_DISPLAY_EXTERNAL) {
341     DLOGE("Not supported for display");
342   } else if (!hwc_display_[disp_idx]) {
343     DLOGW("Display is not connected");
344   } else {
345     return hwc_display_[disp_idx]->OnMinHdcpEncryptionLevelChange(min_enc_level);
346   }
347 
348   return -EINVAL;
349 }
350 
minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,uint32_t min_enc_level)351 Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
352                                                           uint32_t min_enc_level) {
353   return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
354 }
355 
refreshScreen()356 Return<int32_t> HWCSession::refreshScreen() {
357   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
358   Refresh(HWC_DISPLAY_PRIMARY);
359 
360   return 0;
361 }
362 
ControlPartialUpdate(int disp_id,bool enable)363 int32_t 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   Refresh(HWC_DISPLAY_PRIMARY);
397 
398   // Wait until partial update control is complete
399   int32_t error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
400 
401   return error;
402 }
403 
controlPartialUpdate(IDisplayConfig::DisplayType dpy,bool enable)404 Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
405   return ControlPartialUpdate(MapDisplayType(dpy), enable);
406 }
407 
toggleScreenUpdate(bool on)408 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
409   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
410 
411   int32_t 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 
setIdleTimeout(uint32_t value)422 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
423   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
424 
425   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
426     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
427     return 0;
428   }
429 
430   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
431   return -ENODEV;
432 }
433 
getHDRCapabilities(IDisplayConfig::DisplayType dpy,getHDRCapabilities_cb _hidl_cb)434 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
435                                             getHDRCapabilities_cb _hidl_cb) {
436   int32_t error = -EINVAL;
437   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
438 
439   do {
440     if (!_hidl_cb) {
441       DLOGE("_hidl_cb callback not provided.");
442       break;
443     }
444 
445     int disp_id = MapDisplayType(dpy);
446     int disp_idx = GetDisplayIndex(disp_id);
447     if (disp_idx == -1) {
448       DLOGE("Invalid display = %d", disp_id);
449       break;
450     }
451 
452     SCOPE_LOCK(locker_[disp_id]);
453     HWCDisplay *hwc_display = hwc_display_[disp_idx];
454     if (!hwc_display) {
455       DLOGW("Display = %d is not connected.", disp_idx);
456       error = -ENODEV;
457       break;
458     }
459 
460     // query number of hdr types
461     uint32_t out_num_types = 0;
462     float out_max_luminance = 0.0f;
463     float out_max_average_luminance = 0.0f;
464     float out_min_luminance = 0.0f;
465     if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
466                                         &out_max_average_luminance, &out_min_luminance)
467                                         != HWC2::Error::None) {
468       break;
469     }
470     if (!out_num_types) {
471       error = 0;
472       break;
473     }
474 
475     // query hdr caps
476     hdr_caps.supportedHdrTypes.resize(out_num_types);
477 
478     if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
479                                         &out_max_luminance, &out_max_average_luminance,
480                                         &out_min_luminance) == HWC2::Error::None) {
481       error = 0;
482     }
483   } while (false);
484 
485   _hidl_cb(error, hdr_caps);
486 
487   return Void();
488 }
489 
setCameraLaunchStatus(uint32_t on)490 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
491   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
492   if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
493     DLOGE("No active displays");
494     return -EINVAL;
495   }
496   SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
497 
498   if (null_display_mode_) {
499     return 0;
500   }
501 
502   if (!core_intf_) {
503     DLOGW("core_intf_ not initialized.");
504     return -ENOENT;
505   }
506 
507   if (!hwc_display_[active_builtin_disp_id]) {
508     DLOGW("Display = %d is not connected.", active_builtin_disp_id);
509     return -ENODEV;
510   }
511 
512   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
513 
514   // trigger invalidate to apply new bw caps.
515   Refresh(active_builtin_disp_id);
516 
517   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
518     return -EINVAL;
519   }
520 
521   new_bw_mode_ = true;
522   need_invalidate_ = true;
523   hwc_display_[active_builtin_disp_id]->ResetValidation();
524 
525   return 0;
526 }
527 
DisplayBWTransactionPending(bool * status)528 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
529   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
530 
531   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
532     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
533       DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
534       *status = false;
535     }
536 
537     return 0;
538   }
539 
540   DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
541   return -ENODEV;
542 }
543 
displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb)544 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
545   bool status = true;
546 
547   if (!_hidl_cb) {
548       DLOGE("_hidl_cb callback not provided.");
549       return Void();
550   }
551 
552   int32_t error = DisplayBWTransactionPending(&status);
553 
554   _hidl_cb(error, status);
555 
556   return Void();
557 }
558 
559 #ifdef DISPLAY_CONFIG_1_1
setDisplayAnimating(uint64_t display_id,bool animating)560 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
561   return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
562                              &HWCDisplay::SetDisplayAnimating, animating);
563 }
564 #endif
565 
566 #ifdef DISPLAY_CONFIG_1_2
setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,uint32_t base,uint32_t count)567 Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
568                                             uint32_t base, uint32_t count) {
569   return -1;
570 }
571 #endif  // DISPLAY_CONFIG_1_2
572 
573 #ifdef DISPLAY_CONFIG_1_3
controlIdlePowerCollapse(bool enable,bool synchronous)574 Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
575   hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
576   if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
577     DLOGE("No active displays");
578     return -EINVAL;
579   }
580   SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
581 
582   if (hwc_display_[active_builtin_disp_id]) {
583     if (!enable) {
584       if (!idle_pc_ref_cnt_) {
585         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
586                                                                                   synchronous);
587         if (err != kErrorNone) {
588           return (err == kErrorNotSupported) ? 0 : -EINVAL;
589         }
590         Refresh(active_builtin_disp_id);
591         int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
592         if (error == ETIMEDOUT) {
593           DLOGE("Timed out!! Next frame commit done event not received!!");
594           return error;
595         }
596         DLOGI("Idle PC disabled!!");
597       }
598       idle_pc_ref_cnt_++;
599     } else if (idle_pc_ref_cnt_ > 0) {
600       if (!(idle_pc_ref_cnt_ - 1)) {
601         auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
602                                                                                   synchronous);
603         if (err != kErrorNone) {
604           return (err == kErrorNotSupported) ? 0 : -EINVAL;
605         }
606         DLOGI("Idle PC enabled!!");
607       }
608       idle_pc_ref_cnt_--;
609     }
610     return 0;
611   }
612 
613   DLOGW("Display = %d is not connected.", active_builtin_disp_id);
614   return -ENODEV;
615 }
616 #endif  // DISPLAY_CONFIG_1_3
617 
618 
IsWbUbwcSupported(int * value)619 int32_t HWCSession::IsWbUbwcSupported(int *value) {
620   HWDisplaysInfo hw_displays_info = {};
621   DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
622   if (error != kErrorNone) {
623     return -EINVAL;
624   }
625 
626   for (auto &iter : hw_displays_info) {
627     auto &info = iter.second;
628     if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
629       *value = 1;
630     }
631   }
632 
633   return error;
634 }
635 
636 #ifdef DISPLAY_CONFIG_1_4
getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb)637 Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
638   int value = 0;
639   IDisplayConfig::WriteBackCapabilities wb_caps = {};
640   int32_t error = IsWbUbwcSupported(&value);
641   wb_caps.isWbUbwcSupported = value;
642   _hidl_cb(error, wb_caps);
643 
644   return Void();
645 }
646 #endif  // DISPLAY_CONFIG_1_4
647 
648 #ifdef DISPLAY_CONFIG_1_5
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)649 Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
650                                                 uint32_t h_end, uint32_t v_start, uint32_t v_end,
651                                                 uint32_t factor_in, uint32_t factor_out) {
652   return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
653                              &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
654                              factor_in, factor_out);
655 }
656 #endif  // DISPLAY_CONFIG_1_5
657 
658 #ifdef DISPLAY_CONFIG_1_6
updateVSyncSourceOnPowerModeOff()659 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeOff() {
660   return 0;
661 }
662 
updateVSyncSourceOnPowerModeDoze()663 Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeDoze() {
664   return 0;
665 }
666 #endif
667 
668 #ifdef DISPLAY_CONFIG_1_7
setPowerMode(uint32_t disp_id,PowerMode power_mode)669 Return<int32_t> HWCSession::setPowerMode(uint32_t disp_id, PowerMode power_mode) {
670   return 0;
671 }
672 
isPowerModeOverrideSupported(uint32_t disp_id)673 Return<bool> HWCSession::isPowerModeOverrideSupported(uint32_t disp_id) {
674   return false;
675 }
676 
isHDRSupported(uint32_t disp_id)677 Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
678   if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
679     DLOGE("Not valid display");
680     return false;
681   }
682   return static_cast<bool>(is_hdr_display_[disp_id]);
683 }
684 
isWCGSupported(uint32_t disp_id)685 Return<bool> HWCSession::isWCGSupported(uint32_t disp_id) {
686   // todo(user): Query wcg from sdm. For now assume them same.
687   return isHDRSupported(disp_id);
688 }
689 
setLayerAsMask(uint32_t disp_id,uint64_t layer_id)690 Return<int32_t> HWCSession::setLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
691   SCOPE_LOCK(locker_[disp_id]);
692   HWCDisplay *hwc_display = hwc_display_[disp_id];
693   if (!hwc_display) {
694     DLOGW("Display = %d is not connected.", disp_id);
695     return -EINVAL;
696   }
697 
698   if (disable_mask_layer_hint_) {
699     DLOGW("Mask layer hint is disabled!");
700     return -EINVAL;
701   }
702 
703   auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
704   if (hwc_layer == nullptr) {
705     return -EINVAL;
706   }
707 
708   hwc_layer->SetLayerAsMask();
709 
710   return 0;
711 }
712 
getDebugProperty(const hidl_string & prop_name,getDebugProperty_cb _hidl_cb)713 Return<void> HWCSession::getDebugProperty(const hidl_string &prop_name,
714                                           getDebugProperty_cb _hidl_cb) {
715   std::string vendor_prop_name = DISP_PROP_PREFIX;
716   char value[64] = {};
717   hidl_string result = "";
718   int32_t error = -EINVAL;
719 
720   vendor_prop_name += prop_name.c_str();
721   if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) != kErrorNone) {
722     result = value;
723     error = 0;
724   }
725 
726   _hidl_cb(result, error);
727 
728   return Void();
729 }
730 #endif
731 
732 #ifdef DISPLAY_CONFIG_1_8
getActiveBuiltinDisplayAttributes(getDisplayAttributes_cb _hidl_cb)733 Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
734                                           getDisplayAttributes_cb _hidl_cb) {
735   int32_t error = -EINVAL;
736   IDisplayConfig::DisplayAttributes display_attributes = {};
737   hwc2_display_t disp_id = GetActiveBuiltinDisplay();
738 
739   if (disp_id >= HWCCallbacks::kNumDisplays) {
740     DLOGE("Invalid display = %d", disp_id);
741   } else {
742     if (hwc_display_[disp_id]) {
743       uint32_t config_index = 0;
744       HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
745       if (ret != HWC2::Error::None) {
746         goto err;
747       }
748       DisplayConfigVariableInfo var_info;
749       error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
750       if (!error) {
751         display_attributes.vsyncPeriod = var_info.vsync_period_ns;
752         display_attributes.xRes = var_info.x_pixels;
753         display_attributes.yRes = var_info.y_pixels;
754         display_attributes.xDpi = var_info.x_dpi;
755         display_attributes.yDpi = var_info.y_dpi;
756         display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
757         display_attributes.isYuv = var_info.is_yuv;
758       }
759     }
760   }
761 
762 err:
763   _hidl_cb(error, display_attributes);
764 
765   return Void();
766 }
767 #endif  // DISPLAY_CONFIG_1_8
768 
769 }  // namespace sdm
770