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