1 /*
2 * Copyright (c) 2017-2018, 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 <profiler.h>
34 
35 #include "hwc_buffer_sync_handler.h"
36 #include "hwc_session.h"
37 
38 #define __CLASS__ "HWCSession"
39 
40 namespace sdm {
41 
42 using ::android::hardware::Void;
43 
StartServices()44 void HWCSession::StartServices() {
45   status_t status = IDisplayConfig::registerAsService();
46   if (status != OK) {
47     ALOGW("%s::%s: Could not register IDisplayConfig as service (%d).",
48           __CLASS__, __FUNCTION__, status);
49   } else {
50     ALOGI("%s::%s: IDisplayConfig service registration completed.", __CLASS__, __FUNCTION__);
51   }
52 }
53 
MapDisplayType(IDisplayConfig::DisplayType dpy)54 int MapDisplayType(IDisplayConfig::DisplayType dpy) {
55   switch (dpy) {
56     case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
57       return HWC_DISPLAY_PRIMARY;
58 
59     case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
60       return HWC_DISPLAY_EXTERNAL;
61 
62     case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
63       return HWC_DISPLAY_VIRTUAL;
64 
65     default:
66       break;
67   }
68 
69   return -EINVAL;
70 }
71 
MapExternalStatus(IDisplayConfig::DisplayExternalStatus status)72 HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) {
73   switch (status) {
74     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE:
75       return HWCDisplay::kDisplayStatusOffline;
76 
77     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE:
78       return HWCDisplay::kDisplayStatusOnline;
79 
80     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE:
81       return HWCDisplay::kDisplayStatusPause;
82 
83     case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME:
84       return HWCDisplay::kDisplayStatusResume;
85 
86     default:
87       break;
88   }
89 
90   return HWCDisplay::kDisplayStatusInvalid;
91 }
92 
93 // Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow.
isDisplayConnected(IDisplayConfig::DisplayType dpy,isDisplayConnected_cb _hidl_cb)94 Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
95                                             isDisplayConnected_cb _hidl_cb) {
96   int32_t error = -EINVAL;
97   bool connected = false;
98 
99   int disp_id = MapDisplayType(dpy);
100 
101   if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
102     _hidl_cb(error, connected);
103     return Void();
104   }
105 
106   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
107 
108   if (disp_id >= 0) {
109     connected = hwc_display_[disp_id];
110     error = 0;
111   }
112 
113   _hidl_cb(error, connected);
114 
115   return Void();
116 }
117 
SetSecondaryDisplayStatus(int disp_id,HWCDisplay::DisplayStatus status)118 int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
119   if (disp_id < 0) {
120     return -EINVAL;
121   }
122 
123   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
124   DLOGI("Display = %d, Status = %d", disp_id, status);
125 
126   if (disp_id == HWC_DISPLAY_PRIMARY) {
127     DLOGE("Not supported for this display");
128   } else if (!hwc_display_[disp_id]) {
129     DLOGW("Display is not connected");
130   } else {
131     return hwc_display_[disp_id]->SetDisplayStatus(status);
132   }
133 
134   return -EINVAL;
135 }
136 
setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,IDisplayConfig::DisplayExternalStatus status)137 Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
138                                                   IDisplayConfig::DisplayExternalStatus status) {
139   return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
140 }
141 
configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,uint32_t refreshRate)142 Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
143                                                    uint32_t refreshRate) {
144   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
145   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
146 
147   switch (op) {
148     case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
149       return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false);
150 
151     case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
152       return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true);
153 
154     case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
155       return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
156 
157     default:
158       DLOGW("Invalid operation %d", op);
159       return -EINVAL;
160   }
161 
162   return 0;
163 }
164 
GetConfigCount(int disp_id,uint32_t * count)165 int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
166   if (disp_id < 0) {
167     return -EINVAL;
168   }
169 
170   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
171 
172   if (hwc_display_[disp_id]) {
173     return hwc_display_[disp_id]->GetDisplayConfigCount(count);
174   }
175 
176   return -EINVAL;
177 }
178 
getConfigCount(IDisplayConfig::DisplayType dpy,getConfigCount_cb _hidl_cb)179 Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
180                                         getConfigCount_cb _hidl_cb) {
181   uint32_t count = 0;
182   int32_t error = GetConfigCount(MapDisplayType(dpy), &count);
183 
184   _hidl_cb(error, count);
185 
186   return Void();
187 }
188 
GetActiveConfigIndex(int disp_id,uint32_t * config)189 int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
190   if (disp_id < 0) {
191     return -EINVAL;
192   }
193 
194   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
195 
196   if (hwc_display_[disp_id]) {
197     return hwc_display_[disp_id]->GetActiveDisplayConfig(config);
198   }
199 
200   return -EINVAL;
201 }
202 
getActiveConfig(IDisplayConfig::DisplayType dpy,getActiveConfig_cb _hidl_cb)203 Return<void> HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy,
204                                          getActiveConfig_cb _hidl_cb) {
205   uint32_t config = 0;
206   int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config);
207 
208   _hidl_cb(error, config);
209 
210   return Void();
211 }
212 
SetActiveConfigIndex(int disp_id,uint32_t config)213 int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
214   if (disp_id < 0) {
215     return -EINVAL;
216   }
217 
218   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
219   int32_t error = -EINVAL;
220   if (hwc_display_[disp_id]) {
221     error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
222     if (!error) {
223       Refresh(0);
224     }
225   }
226 
227   return error;
228 }
229 
setActiveConfig(IDisplayConfig::DisplayType dpy,uint32_t config)230 Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
231   return SetActiveConfigIndex(MapDisplayType(dpy), config);
232 }
233 
getDisplayAttributes(uint32_t configIndex,IDisplayConfig::DisplayType dpy,getDisplayAttributes_cb _hidl_cb)234 Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
235                                               IDisplayConfig::DisplayType dpy,
236                                               getDisplayAttributes_cb _hidl_cb) {
237   int32_t error = -EINVAL;
238   IDisplayConfig::DisplayAttributes display_attributes = {};
239   int disp_id = MapDisplayType(dpy);
240 
241   if (disp_id >= HWC_DISPLAY_PRIMARY && disp_id < HWC_NUM_DISPLAY_TYPES) {
242     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
243     if (hwc_display_[disp_id]) {
244       DisplayConfigVariableInfo hwc_display_attributes;
245       error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast<int>(configIndex),
246                                                                  &hwc_display_attributes);
247       if (!error) {
248         display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns;
249         display_attributes.xRes = hwc_display_attributes.x_pixels;
250         display_attributes.yRes = hwc_display_attributes.y_pixels;
251         display_attributes.xDpi = hwc_display_attributes.x_dpi;
252         display_attributes.yDpi = hwc_display_attributes.y_dpi;
253         display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
254         display_attributes.isYuv = hwc_display_attributes.is_yuv;
255       }
256     }
257   }
258   _hidl_cb(error, display_attributes);
259 
260   return Void();
261 }
262 
setPanelBrightness(uint32_t level)263 Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
264   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
265   int32_t error = -EINVAL;
266 
267   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
268     error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast<int>(level));
269     if (error) {
270       DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error);
271     }
272   }
273 
274   return error;
275 }
276 
GetPanelBrightness(int * level)277 int32_t HWCSession::GetPanelBrightness(int *level) {
278   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
279   int32_t error = -EINVAL;
280 
281   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
282     error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level);
283     if (error) {
284       DLOGE("Failed to get the panel brightness. Error = %d", error);
285     }
286   }
287 
288   return error;
289 }
290 
getPanelBrightness(getPanelBrightness_cb _hidl_cb)291 Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
292   int level = 0;
293   int32_t error = GetPanelBrightness(&level);
294 
295   _hidl_cb(error, static_cast<uint32_t>(level));
296 
297   return Void();
298 }
299 
MinHdcpEncryptionLevelChanged(int disp_id,uint32_t min_enc_level)300 int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
301   DLOGI("Display %d", disp_id);
302 
303   if (disp_id < 0) {
304     return -EINVAL;
305   }
306 
307   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
308   if (disp_id != HWC_DISPLAY_EXTERNAL) {
309     DLOGE("Not supported for display");
310   } else if (!hwc_display_[disp_id]) {
311     DLOGW("Display is not connected");
312   } else {
313     return hwc_display_[disp_id]->OnMinHdcpEncryptionLevelChange(min_enc_level);
314   }
315 
316   return -EINVAL;
317 }
318 
minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,uint32_t min_enc_level)319 Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
320                                                           uint32_t min_enc_level) {
321   return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
322 }
323 
refreshScreen()324 Return<int32_t> HWCSession::refreshScreen() {
325   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
326   Refresh(HWC_DISPLAY_PRIMARY);
327 
328   return 0;
329 }
330 
ControlPartialUpdate(int disp_id,bool enable)331 int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
332   if (disp_id < 0) {
333     return -EINVAL;
334   }
335 
336   if (disp_id != HWC_DISPLAY_PRIMARY) {
337     DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id);
338     return -EINVAL;
339   }
340 
341   SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
342   HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
343   if (!hwc_display) {
344     DLOGE("primary display object is not instantiated");
345     return -EINVAL;
346   }
347 
348   uint32_t pending = 0;
349   DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
350 
351   if (hwc_error == kErrorNone) {
352     if (!pending) {
353       return 0;
354     }
355   } else if (hwc_error == kErrorNotSupported) {
356     return 0;
357   } else {
358     return -EINVAL;
359   }
360 
361   // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
362   Refresh(HWC_DISPLAY_PRIMARY);
363 
364   // Wait until partial update control is complete
365   int32_t error = locker_[disp_id].WaitFinite(kPartialUpdateControlTimeoutMs);
366 
367   return error;
368 }
369 
controlPartialUpdate(IDisplayConfig::DisplayType dpy,bool enable)370 Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
371   return ControlPartialUpdate(MapDisplayType(dpy), enable);
372 }
373 
toggleScreenUpdate(bool on)374 Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
375   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
376 
377   int32_t error = -EINVAL;
378   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
379     error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
380     if (error) {
381       DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
382     }
383   }
384 
385   return error;
386 }
387 
setIdleTimeout(uint32_t value)388 Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
389   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
390 
391   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
392     hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
393     return 0;
394   }
395 
396   return -EINVAL;
397 }
398 
getHDRCapabilities(IDisplayConfig::DisplayType dpy,getHDRCapabilities_cb _hidl_cb)399 Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
400                                             getHDRCapabilities_cb _hidl_cb) {
401   int32_t error = -EINVAL;
402   IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
403 
404   do {
405     int disp_id = MapDisplayType(dpy);
406     if ((disp_id < 0) || (disp_id >= HWC_NUM_DISPLAY_TYPES)) {
407       DLOGE("Invalid display id = %d", disp_id);
408       break;
409     }
410 
411     SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
412     HWCDisplay *hwc_display = hwc_display_[disp_id];
413     if (!hwc_display) {
414       DLOGE("Display = %d is not connected.", disp_id);
415       break;
416     }
417 
418     // query number of hdr types
419     uint32_t out_num_types = 0;
420     if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr)
421         != HWC2::Error::None) {
422       break;
423     }
424 
425     if (!out_num_types) {
426       error = 0;
427       break;
428     }
429 
430     // query hdr caps
431     hdr_caps.supportedHdrTypes.resize(out_num_types);
432 
433     float out_max_luminance = 0.0f;
434     float out_max_average_luminance = 0.0f;
435     float out_min_luminance = 0.0f;
436     if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
437                                         &out_max_luminance, &out_max_average_luminance,
438                                         &out_min_luminance)
439         == HWC2::Error::None) {
440       error = 0;
441     }
442   } while (false);
443 
444   _hidl_cb(error, hdr_caps);
445 
446   return Void();
447 }
448 
setCameraLaunchStatus(uint32_t on)449 Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
450   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
451 
452   HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
453 
454   // trigger invalidate to apply new bw caps.
455   Refresh(HWC_DISPLAY_PRIMARY);
456 
457   if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
458     return -EINVAL;
459   }
460 
461   new_bw_mode_ = true;
462   need_invalidate_ = true;
463   hwc_display_[HWC_DISPLAY_PRIMARY]->ResetValidation();
464 
465   return 0;
466 }
467 
DisplayBWTransactionPending(bool * status)468 int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
469   SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
470 
471   if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
472     if (sync_wait(bw_mode_release_fd_, 0) < 0) {
473       DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
474       *status = false;
475     }
476 
477     return 0;
478   }
479 
480   return -EINVAL;
481 }
482 
displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb)483 Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
484   bool status = true;
485 
486   int32_t error = DisplayBWTransactionPending(&status);
487 
488   _hidl_cb(error, status);
489 
490   return Void();
491 }
492 
493 #ifdef DISPLAY_CONFIG_1_1
494 // Methods from ::vendor::hardware::display::config::V1_1::IDisplayConfig follow.
setDisplayAnimating(uint64_t display_id,bool animating)495 Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
496   SEQUENCE_WAIT_SCOPE_LOCK(locker_[display_id]);
497   return CallDisplayFunction(static_cast<hwc2_device_t *>(this), display_id,
498                              &HWCDisplay::SetDisplayAnimating, animating);
499 }
500 #endif
501 
502 
503 }  // namespace sdm
504