blob: 4728d2071fff96bb55c77e225f7deb30e8b6099d [file] [log] [blame]
Dileep Marchya6860b2b2017-04-07 15:56:47 +05301/*
Ramakant Singh0a571062019-01-04 13:19:31 +05302* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
Dileep Marchya6860b2b2017-04-07 15:56:47 +05303*
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>
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +053033#include <vector>
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +053034#include <string>
Dileep Marchya6860b2b2017-04-07 15:56:47 +053035
36#include "hwc_buffer_sync_handler.h"
37#include "hwc_session.h"
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +053038#include "hwc_debugger.h"
Dileep Marchya6860b2b2017-04-07 15:56:47 +053039
40#define __CLASS__ "HWCSession"
41
42namespace sdm {
43
44using ::android::hardware::Void;
45
46void HWCSession::StartServices() {
Saurabh Shah546f77b2017-12-13 14:10:39 -080047 android::status_t status = IDisplayConfig::registerAsService();
48 if (status != android::OK) {
Dileep Marchya4cb86b42018-05-01 19:34:51 +053049 DLOGW("Could not register IDisplayConfig as service (%d).", status);
Dileep Marchya6860b2b2017-04-07 15:56:47 +053050 } else {
Dileep Marchya4cb86b42018-05-01 19:34:51 +053051 DLOGI("IDisplayConfig service registration completed.");
Dileep Marchya6860b2b2017-04-07 15:56:47 +053052 }
53}
54
55int MapDisplayType(IDisplayConfig::DisplayType dpy) {
56 switch (dpy) {
57 case IDisplayConfig::DisplayType::DISPLAY_PRIMARY:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +053058 return qdutils::DISPLAY_PRIMARY;
Dileep Marchya6860b2b2017-04-07 15:56:47 +053059
60 case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +053061 return qdutils::DISPLAY_EXTERNAL;
Dileep Marchya6860b2b2017-04-07 15:56:47 +053062
63 case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +053064 return qdutils::DISPLAY_VIRTUAL;
Dileep Marchya6860b2b2017-04-07 15:56:47 +053065
66 default:
67 break;
68 }
69
70 return -EINVAL;
71}
72
73HWCDisplay::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.
95Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
96 isDisplayConnected_cb _hidl_cb) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +053097 int32_t error = -EINVAL;
98 bool connected = false;
Dileep Marchya6860b2b2017-04-07 15:56:47 +053099 int disp_id = MapDisplayType(dpy);
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530100 int disp_idx = GetDisplayIndex(disp_id);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700101
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530102 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;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530108 }
Varun Arora2c23e582017-10-10 15:07:13 -0700109 _hidl_cb(error, connected);
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530110
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530111 return Void();
112}
113
114int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530115 int disp_idx = GetDisplayIndex(disp_id);
Ramakant Singh22e4e252019-02-20 22:40:01 +0530116 int err = -EINVAL;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530117 if (disp_idx == -1) {
Varun Arora2c23e582017-10-10 15:07:13 -0700118 DLOGE("Invalid display = %d", disp_id);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530119 return -EINVAL;
120 }
121
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530122 if (disp_idx == qdutils::DISPLAY_PRIMARY) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530123 DLOGE("Not supported for this display");
Ramakant Singh22e4e252019-02-20 22:40:01 +0530124 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);
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800135 if (err != 0) {
136 return err;
137 }
Ramakant Singh22e4e252019-02-20 22:40:01 +0530138 }
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800139
Ramakant Singh22e4e252019-02-20 22:40:01 +0530140 if (status == HWCDisplay::kDisplayStatusResume || status == HWCDisplay::kDisplayStatusPause) {
141 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -0700142 if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
Ramakant Singh22e4e252019-02-20 22:40:01 +0530143 {
144 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
145 hwc_display_[active_builtin_disp_id]->ResetValidation();
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800146 }
Ramakant Singh22e4e252019-02-20 22:40:01 +0530147 callbacks_.Refresh(active_builtin_disp_id);
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800148 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530149 }
150
Ramakant Singh22e4e252019-02-20 22:40:01 +0530151 return err;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530152}
153
154Return<int32_t> HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy,
155 IDisplayConfig::DisplayExternalStatus status) {
156 return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status));
157}
158
159Return<int32_t> HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op,
160 uint32_t refreshRate) {
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700161 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530162 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
163
Alex Sarrafddb44ac2018-06-14 11:22:59 -0700164 if (!hwc_display) {
165 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
166 return -EINVAL;
167 }
168
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530169 switch (op) {
170 case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530171 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, false);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530172
173 case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530174 return hwc_display->Perform(HWCDisplayBuiltIn::SET_METADATA_DYN_REFRESH_RATE, true);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530175
176 case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE:
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530177 return hwc_display->Perform(HWCDisplayBuiltIn::SET_BINDER_DYN_REFRESH_RATE, refreshRate);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530178
179 default:
180 DLOGW("Invalid operation %d", op);
181 return -EINVAL;
182 }
183
184 return 0;
185}
186
187int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530188 int disp_idx = GetDisplayIndex(disp_id);
189 if (disp_idx == -1) {
190 DLOGE("Invalid display = %d", disp_id);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700191 return -EINVAL;
192 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530193
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530194 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700195
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530196 if (hwc_display_[disp_idx]) {
197 return hwc_display_[disp_idx]->GetDisplayConfigCount(count);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530198 }
199
200 return -EINVAL;
201}
202
203Return<void> HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy,
204 getConfigCount_cb _hidl_cb) {
205 uint32_t count = 0;
Uday Kiran Pichika2b396bc2017-07-06 17:24:54 +0530206 int32_t error = GetConfigCount(MapDisplayType(dpy), &count);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530207
208 _hidl_cb(error, count);
209
210 return Void();
211}
212
213int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530214 int disp_idx = GetDisplayIndex(disp_id);
215 if (disp_idx == -1) {
216 DLOGE("Invalid display = %d", disp_id);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700217 return -EINVAL;
218 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530219
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530220 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700221
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530222 if (hwc_display_[disp_idx]) {
223 return hwc_display_[disp_idx]->GetActiveDisplayConfig(config);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530224 }
225
226 return -EINVAL;
227}
228
229Return<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
239int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530240 int disp_idx = GetDisplayIndex(disp_id);
241 if (disp_idx == -1) {
242 DLOGE("Invalid display = %d", disp_id);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530243 return -EINVAL;
244 }
245
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530246 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530247 int32_t error = -EINVAL;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530248 if (hwc_display_[disp_idx]) {
249 error = hwc_display_[disp_idx]->SetActiveDisplayConfig(config);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530250 if (!error) {
Varun Aroradff7d8d2019-08-05 18:12:43 -0700251 callbacks_.Refresh(0);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530252 }
253 }
254
255 return error;
256}
257
258Return<int32_t> HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) {
259 return SetActiveConfigIndex(MapDisplayType(dpy), config);
260}
261
262Return<void> HWCSession::getDisplayAttributes(uint32_t configIndex,
263 IDisplayConfig::DisplayType dpy,
264 getDisplayAttributes_cb _hidl_cb) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530265 int32_t error = -EINVAL;
266 IDisplayConfig::DisplayAttributes display_attributes = {};
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530267 int disp_id = MapDisplayType(dpy);
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530268 int disp_idx = GetDisplayIndex(disp_id);
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700269
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530270 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);
Ramkumar Radhakrishnan6b05e5d2017-11-21 13:50:10 -0800277 if (!error) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530278 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;
Ramkumar Radhakrishnan6b05e5d2017-11-21 13:50:10 -0800283 display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530284 display_attributes.isYuv = var_info.is_yuv;
Ramkumar Radhakrishnan6b05e5d2017-11-21 13:50:10 -0800285 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530286 }
287 }
Brahmaji K0b90f9d2017-10-31 01:57:40 +0530288 _hidl_cb(error, display_attributes);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530289
290 return Void();
291}
292
293Return<int32_t> HWCSession::setPanelBrightness(uint32_t level) {
Varun Arora75c05f02019-05-14 14:53:37 -0700294 if (!(0 <= level && level <= 255)) {
295 return -EINVAL;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530296 }
297
Varun Arora75c05f02019-05-14 14:53:37 -0700298 if (level == 0) {
Rajavenu Kyatham42d11cb2019-04-16 13:03:29 +0530299 return INT32(SetDisplayBrightness(HWC_DISPLAY_PRIMARY, -1.0f));
Varun Arora75c05f02019-05-14 14:53:37 -0700300 } else {
Rajavenu Kyatham42d11cb2019-04-16 13:03:29 +0530301 return INT32(SetDisplayBrightness(HWC_DISPLAY_PRIMARY, (level - 1)/254.0f));
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530302 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530303}
304
305Return<void> HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) {
Varun Arora75c05f02019-05-14 14:53:37 -0700306 float brightness = -1.0f;
307 int32_t error = -EINVAL;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530308
Varun Arora75c05f02019-05-14 14:53:37 -0700309 error = getDisplayBrightness(HWC_DISPLAY_PRIMARY, &brightness);
310 if (brightness == -1.0f) {
311 _hidl_cb(error, 0);
312 } else {
313 _hidl_cb(error, static_cast<uint32_t>(254.0f*brightness + 1));
314 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530315
316 return Void();
317}
318
319int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530320 DLOGI("Display %d", disp_id);
321
Subash Chander163d1522019-02-15 14:07:41 +0530322 int disp_idx = GetDisplayIndex(disp_id);
323 if (disp_idx == -1) {
324 DLOGE("Invalid display = %d", disp_id);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530325 return -EINVAL;
326 }
327
Subash Chander163d1522019-02-15 14:07:41 +0530328 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
329 if (disp_idx != HWC_DISPLAY_EXTERNAL) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530330 DLOGE("Not supported for display");
Subash Chander163d1522019-02-15 14:07:41 +0530331 } else if (!hwc_display_[disp_idx]) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530332 DLOGW("Display is not connected");
333 } else {
Subash Chander163d1522019-02-15 14:07:41 +0530334 return hwc_display_[disp_idx]->OnMinHdcpEncryptionLevelChange(min_enc_level);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530335 }
336
337 return -EINVAL;
338}
339
340Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy,
341 uint32_t min_enc_level) {
342 return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level);
343}
344
345Return<int32_t> HWCSession::refreshScreen() {
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700346 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Varun Aroradff7d8d2019-08-05 18:12:43 -0700347 callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530348
349 return 0;
350}
351
352int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
Subash Chander163d1522019-02-15 14:07:41 +0530353 int disp_idx = GetDisplayIndex(disp_id);
354 if (disp_idx == -1) {
355 DLOGE("Invalid display = %d", disp_id);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530356 return -EINVAL;
357 }
358
Subash Chander163d1522019-02-15 14:07:41 +0530359 if (disp_idx != HWC_DISPLAY_PRIMARY) {
360 DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_idx);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530361 return -EINVAL;
362 }
363
Subash Chander163d1522019-02-15 14:07:41 +0530364 SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_idx]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530365 HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY];
366 if (!hwc_display) {
367 DLOGE("primary display object is not instantiated");
368 return -EINVAL;
369 }
370
371 uint32_t pending = 0;
372 DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending);
373
374 if (hwc_error == kErrorNone) {
375 if (!pending) {
376 return 0;
377 }
378 } else if (hwc_error == kErrorNotSupported) {
379 return 0;
380 } else {
381 return -EINVAL;
382 }
383
384 // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
Varun Aroradff7d8d2019-08-05 18:12:43 -0700385 callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530386
387 // Wait until partial update control is complete
Subash Chander163d1522019-02-15 14:07:41 +0530388 int32_t error = locker_[disp_idx].WaitFinite(kCommitDoneTimeoutMs);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530389
390 return error;
391}
392
393Return<int32_t> HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) {
394 return ControlPartialUpdate(MapDisplayType(dpy), enable);
395}
396
397Return<int32_t> HWCSession::toggleScreenUpdate(bool on) {
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700398 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530399
400 int32_t error = -EINVAL;
401 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
402 error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on);
403 if (error) {
404 DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error);
405 }
406 }
407
408 return error;
409}
410
411Return<int32_t> HWCSession::setIdleTimeout(uint32_t value) {
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700412 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530413
414 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
415 hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value);
416 return 0;
417 }
418
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +0530419 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
420 return -ENODEV;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530421}
422
423Return<void> HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy,
424 getHDRCapabilities_cb _hidl_cb) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530425 int32_t error = -EINVAL;
426 IDisplayConfig::DisplayHDRCapabilities hdr_caps = {};
427
428 do {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530429 if (!_hidl_cb) {
430 DLOGE("_hidl_cb callback not provided.");
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530431 break;
432 }
433
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530434 int disp_id = MapDisplayType(dpy);
435 int disp_idx = GetDisplayIndex(disp_id);
436 if (disp_idx == -1) {
437 DLOGE("Invalid display = %d", disp_id);
438 break;
439 }
440
Ramakant Singh0a571062019-01-04 13:19:31 +0530441 SCOPE_LOCK(locker_[disp_id]);
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530442 HWCDisplay *hwc_display = hwc_display_[disp_idx];
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530443 if (!hwc_display) {
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530444 DLOGW("Display = %d is not connected.", disp_idx);
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +0530445 error = -ENODEV;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530446 break;
447 }
448
449 // query number of hdr types
450 uint32_t out_num_types = 0;
Ramakant Singh0a571062019-01-04 13:19:31 +0530451 float out_max_luminance = 0.0f;
452 float out_max_average_luminance = 0.0f;
453 float out_min_luminance = 0.0f;
454 if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, &out_max_luminance,
455 &out_max_average_luminance, &out_min_luminance)
456 != HWC2::Error::None) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530457 break;
458 }
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530459 if (!out_num_types) {
460 error = 0;
461 break;
462 }
463
464 // query hdr caps
465 hdr_caps.supportedHdrTypes.resize(out_num_types);
466
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530467 if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(),
468 &out_max_luminance, &out_max_average_luminance,
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530469 &out_min_luminance) == HWC2::Error::None) {
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530470 error = 0;
471 }
472 } while (false);
473
474 _hidl_cb(error, hdr_caps);
475
476 return Void();
477}
478
479Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
Varun Arora465c1f72018-02-08 16:18:50 -0800480 if (null_display_mode_) {
481 return 0;
482 }
483
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +0530484 if (!core_intf_) {
485 DLOGW("core_intf_ not initialized.");
486 return -ENOENT;
487 }
488
Alex Sarraf2092d782019-06-07 17:32:21 -0700489 HWBwModes mode = on > 0 ? kBwVFEOn : kBwVFEOff;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530490
491 if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
492 return -EINVAL;
493 }
494
Alex Sarraf2092d782019-06-07 17:32:21 -0700495 // trigger invalidate to apply new bw caps.
Varun Aroradff7d8d2019-08-05 18:12:43 -0700496 callbacks_.Refresh(0);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530497
498 return 0;
499}
500
501int32_t HWCSession::DisplayBWTransactionPending(bool *status) {
Saurabh Shahc5c687a2017-08-24 16:30:14 -0700502 SEQUENCE_WAIT_SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530503
504 if (hwc_display_[HWC_DISPLAY_PRIMARY]) {
505 if (sync_wait(bw_mode_release_fd_, 0) < 0) {
506 DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno));
507 *status = false;
508 }
509
510 return 0;
511 }
512
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +0530513 DLOGW("Display = %d is not connected.", HWC_DISPLAY_PRIMARY);
514 return -ENODEV;
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530515}
516
517Return<void> HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) {
518 bool status = true;
519
Mathew Joseph Karimpanaldbd64f82017-10-06 10:13:38 +0530520 if (!_hidl_cb) {
521 DLOGE("_hidl_cb callback not provided.");
522 return Void();
523 }
524
Dileep Marchya6860b2b2017-04-07 15:56:47 +0530525 int32_t error = DisplayBWTransactionPending(&status);
526
527 _hidl_cb(error, status);
528
529 return Void();
530}
531
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530532Return<int32_t> HWCSession::setDisplayAnimating(uint64_t display_id, bool animating ) {
Rajavenu Kyatham42d11cb2019-04-16 13:03:29 +0530533 return CallDisplayFunction(display_id,
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530534 &HWCDisplay::SetDisplayAnimating, animating);
535}
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530536
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530537Return<int32_t> HWCSession::setDisplayIndex(IDisplayConfig::DisplayTypeExt disp_type,
538 uint32_t base, uint32_t count) {
Pullakavi Srinivasf2a31852019-04-23 14:32:08 -0700539 return -1;
Dileep Marchyaf3ce11f2018-04-30 23:35:46 +0530540}
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700541
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700542Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchronous) {
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800543 hwc2_display_t active_builtin_disp_id = GetActiveBuiltinDisplay();
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -0700544 if (active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800545 DLOGE("No active displays");
546 return -EINVAL;
547 }
548 SEQUENCE_WAIT_SCOPE_LOCK(locker_[active_builtin_disp_id]);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700549
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800550 if (hwc_display_[active_builtin_disp_id]) {
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700551 if (!enable) {
552 if (!idle_pc_ref_cnt_) {
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800553 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
554 synchronous);
Ramkumar Radhakrishnan4faf8a62018-11-15 17:15:37 -0800555 if (err != kErrorNone) {
556 return (err == kErrorNotSupported) ? 0 : -EINVAL;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700557 }
Varun Aroradff7d8d2019-08-05 18:12:43 -0700558 callbacks_.Refresh(active_builtin_disp_id);
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800559 int32_t error = locker_[active_builtin_disp_id].WaitFinite(kCommitDoneTimeoutMs);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700560 if (error == ETIMEDOUT) {
561 DLOGE("Timed out!! Next frame commit done event not received!!");
562 return error;
563 }
564 DLOGI("Idle PC disabled!!");
565 }
566 idle_pc_ref_cnt_++;
567 } else if (idle_pc_ref_cnt_ > 0) {
568 if (!(idle_pc_ref_cnt_ - 1)) {
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800569 auto err = hwc_display_[active_builtin_disp_id]->ControlIdlePowerCollapse(enable,
570 synchronous);
Ramkumar Radhakrishnan4faf8a62018-11-15 17:15:37 -0800571 if (err != kErrorNone) {
572 return (err == kErrorNotSupported) ? 0 : -EINVAL;
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700573 }
574 DLOGI("Idle PC enabled!!");
575 }
576 idle_pc_ref_cnt_--;
577 }
578 return 0;
579 }
580
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800581 DLOGW("Display = %d is not connected.", active_builtin_disp_id);
Ramkumar Radhakrishnanf985d482018-07-23 18:10:41 -0700582 return -ENODEV;
583}
Ramakant Singhdbe738a2018-08-23 23:57:07 +0530584
585int32_t HWCSession::IsWbUbwcSupported(int *value) {
586 HWDisplaysInfo hw_displays_info = {};
587 DisplayError error = core_intf_->GetDisplaysStatus(&hw_displays_info);
588 if (error != kErrorNone) {
589 return -EINVAL;
590 }
591
592 for (auto &iter : hw_displays_info) {
593 auto &info = iter.second;
594 if (info.display_type == kVirtual && info.is_wb_ubwc_supported) {
595 *value = 1;
596 }
597 }
598
599 return error;
600}
601
Ramakant Singhdbe738a2018-08-23 23:57:07 +0530602Return<void> HWCSession::getWriteBackCapabilities(getWriteBackCapabilities_cb _hidl_cb) {
603 int value = 0;
604 IDisplayConfig::WriteBackCapabilities wb_caps = {};
605 int32_t error = IsWbUbwcSupported(&value);
606 wb_caps.isWbUbwcSupported = value;
607 _hidl_cb(error, wb_caps);
608
609 return Void();
610}
Ramakant Singhdbe738a2018-08-23 23:57:07 +0530611
Yuchao Ma577f0f72018-07-09 11:20:00 +0800612Return<int32_t> HWCSession::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start,
613 uint32_t h_end, uint32_t v_start, uint32_t v_end,
614 uint32_t factor_in, uint32_t factor_out) {
Rajavenu Kyatham42d11cb2019-04-16 13:03:29 +0530615 return CallDisplayFunction(display_id,
Yuchao Ma577f0f72018-07-09 11:20:00 +0800616 &HWCDisplay::SetDisplayDppsAdROI, h_start, h_end, v_start, v_end,
617 factor_in, factor_out);
618}
Yuchao Ma577f0f72018-07-09 11:20:00 +0800619
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530620Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeOff() {
Padmanabhan Komanduru8e1457a2019-02-22 17:10:41 +0530621 update_vsync_on_power_off_ = true;
622
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530623 return 0;
624}
625
626Return<int32_t> HWCSession::updateVSyncSourceOnPowerModeDoze() {
Padmanabhan Komanduru8e1457a2019-02-22 17:10:41 +0530627 update_vsync_on_doze_ = true;
628
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530629 return 0;
630}
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530631
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530632Return<bool> HWCSession::isPowerModeOverrideSupported(uint32_t disp_id) {
633 if (!async_powermode_ || (disp_id > HWCCallbacks::kNumRealDisplays)) {
634 return false;
635 }
636
637 return true;
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530638}
639
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530640Return<int32_t> HWCSession::setPowerMode(uint32_t disp_id, PowerMode power_mode) {
641 SCOPE_LOCK(display_config_locker_);
642
643 if (!isPowerModeOverrideSupported(disp_id)) {
644 return 0;
645 }
646
647 DLOGI("disp_id: %d power_mode: %d", disp_id, power_mode);
648 HWCDisplay::HWCLayerStack stack = {};
649 hwc2_display_t dummy_disp_id = map_hwc_display_.at(disp_id);
650
Mathew Joseph Karimpanalf32a4c62019-08-27 18:42:40 +0530651 // Power state transition start.
652 power_state_[disp_id].Lock(); // Acquire the display's power-state transition var read lock.
653 power_state_transition_[disp_id] = true;
654 locker_[disp_id].Lock(); // Lock the real display.
655 locker_[dummy_disp_id].Lock(); // Lock the corresponding dummy display.
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530656
Mathew Joseph Karimpanalf32a4c62019-08-27 18:42:40 +0530657 // Place the real display's layer-stack on the dummy display.
658 hwc_display_[disp_id]->GetLayerStack(&stack);
659 hwc_display_[dummy_disp_id]->SetLayerStack(&stack);
660 hwc_display_[dummy_disp_id]->UpdatePowerMode(hwc_display_[disp_id]->GetCurrentPowerMode());
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530661
Mathew Joseph Karimpanalf32a4c62019-08-27 18:42:40 +0530662 locker_[dummy_disp_id].Unlock(); // Release the dummy display.
663 power_state_[disp_id].Unlock(); // Release the display's power-state transition var read lock.
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530664
Mathew Joseph Karimpanalf32a4c62019-08-27 18:42:40 +0530665 // From now, till power-state transition ends, for operations that need to be non-blocking, do
666 // those operations on the dummy display.
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530667
Mathew Joseph Karimpanalf32a4c62019-08-27 18:42:40 +0530668 // Perform the actual [synchronous] power-state change.
669 hwc_display_[disp_id]->SetPowerMode(static_cast<HWC2::PowerMode>(power_mode),
670 false /* teardown */);
671
672 // Power state transition end.
673 power_state_[disp_id].Lock(); // Acquire the display's power-state transition var read lock.
674 power_state_transition_[disp_id] = false;
675 locker_[dummy_disp_id].Lock(); // Lock the dummy display.
676
677 // Retrieve the real display's layer-stack from the dummy display.
678 hwc_display_[dummy_disp_id]->GetLayerStack(&stack);
679 hwc_display_[disp_id]->SetLayerStack(&stack);
680 // Read display has got layerstack. Update the fences.
681 hwc_display_[disp_id]->PostPowerMode();
682
683 locker_[dummy_disp_id].Unlock(); // Release the dummy display.
684 locker_[disp_id].Unlock(); // Release the real display.
685 power_state_[disp_id].Unlock(); // Release the display's power-state transition var read lock.
Srinivas Pullakavi3c4337f2019-07-03 11:24:31 +0530686
687 return 0;
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530688}
689
690Return<bool> HWCSession::isHDRSupported(uint32_t disp_id) {
Archit Srivastavafe060f72019-05-27 15:51:58 +0530691 if (disp_id < 0 || disp_id >= HWCCallbacks::kNumDisplays) {
692 DLOGE("Not valid display");
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530693 return false;
694 }
Archit Srivastavafe060f72019-05-27 15:51:58 +0530695 return static_cast<bool>(is_hdr_display_[disp_id]);
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530696}
697
698Return<bool> HWCSession::isWCGSupported(uint32_t disp_id) {
699 // todo(user): Query wcg from sdm. For now assume them same.
700 return isHDRSupported(disp_id);
701}
702
703Return<int32_t> HWCSession::setLayerAsMask(uint32_t disp_id, uint64_t layer_id) {
Pullakavi Srinivas2fbff8d2019-04-22 18:32:52 -0700704 SCOPE_LOCK(locker_[disp_id]);
705 HWCDisplay *hwc_display = hwc_display_[disp_id];
706 if (!hwc_display) {
707 DLOGW("Display = %d is not connected.", disp_id);
708 return -EINVAL;
709 }
710
711 if (disable_mask_layer_hint_) {
712 DLOGW("Mask layer hint is disabled!");
713 return -EINVAL;
714 }
715
716 auto hwc_layer = hwc_display->GetHWCLayer(layer_id);
717 if (hwc_layer == nullptr) {
718 return -EINVAL;
719 }
720
721 hwc_layer->SetLayerAsMask();
722
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530723 return 0;
724}
725
726Return<void> HWCSession::getDebugProperty(const hidl_string &prop_name,
727 getDebugProperty_cb _hidl_cb) {
728 std::string vendor_prop_name = DISP_PROP_PREFIX;
729 char value[64] = {};
730 hidl_string result = "";
731 int32_t error = -EINVAL;
732
733 vendor_prop_name += prop_name.c_str();
734 if (HWCDebugHandler::Get()->GetProperty(vendor_prop_name.c_str(), value) != kErrorNone) {
735 result = value;
736 error = 0;
737 }
738
739 _hidl_cb(result, error);
740
741 return Void();
742}
Dileep Marchyae1c7c8d2018-12-06 15:27:45 +0530743
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800744Return<void> HWCSession::getActiveBuiltinDisplayAttributes(
745 getDisplayAttributes_cb _hidl_cb) {
746 int32_t error = -EINVAL;
747 IDisplayConfig::DisplayAttributes display_attributes = {};
748 hwc2_display_t disp_id = GetActiveBuiltinDisplay();
749
Padmanabhan Komandurue74cf4f2019-04-25 17:38:43 -0700750 if (disp_id >= HWCCallbacks::kNumDisplays) {
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800751 DLOGE("Invalid display = %d", disp_id);
752 } else {
753 if (hwc_display_[disp_id]) {
754 uint32_t config_index = 0;
755 HWC2::Error ret = hwc_display_[disp_id]->GetActiveConfig(&config_index);
756 if (ret != HWC2::Error::None) {
757 goto err;
758 }
759 DisplayConfigVariableInfo var_info;
760 error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(INT(config_index), &var_info);
761 if (!error) {
762 display_attributes.vsyncPeriod = var_info.vsync_period_ns;
763 display_attributes.xRes = var_info.x_pixels;
764 display_attributes.yRes = var_info.y_pixels;
765 display_attributes.xDpi = var_info.x_dpi;
766 display_attributes.yDpi = var_info.y_dpi;
767 display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT;
768 display_attributes.isYuv = var_info.is_yuv;
769 }
770 }
771 }
772
773err:
774 _hidl_cb(error, display_attributes);
775
776 return Void();
777}
Ramkumar Radhakrishnan44c64362018-12-12 13:03:59 -0800778
Varun Arora75c05f02019-05-14 14:53:37 -0700779int32_t HWCSession::getDisplayBrightness(uint32_t display, float *brightness) {
780 if (!brightness) {
781 return HWC2_ERROR_BAD_PARAMETER;
782 }
783
784 if (display >= HWCCallbacks::kNumDisplays) {
785 return HWC2_ERROR_BAD_DISPLAY;
786 }
787
788 SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
789 int32_t error = -EINVAL;
790 *brightness = -1.0f;
791
792 HWCDisplay *hwc_display = hwc_display_[display];
793 if (hwc_display && hwc_display_[display]->GetDisplayClass() == DISPLAY_CLASS_BUILTIN) {
794 error = INT32(hwc_display_[display]->GetPanelBrightness(brightness));
795 if (error) {
796 DLOGE("Failed to get the panel brightness. Error = %d", error);
797 }
798 }
799
800 return error;
801}
802
803int32_t HWCSession::setDisplayBrightness(uint32_t display, float brightness) {
Rajavenu Kyatham42d11cb2019-04-16 13:03:29 +0530804 return SetDisplayBrightness(static_cast<hwc2_display_t>(display), brightness);
Varun Arora75c05f02019-05-14 14:53:37 -0700805}
Archit Srivastavaa59c4ff2019-05-20 10:54:22 +0530806
Archit Srivastavaa59c4ff2019-05-20 10:54:22 +0530807Return<int32_t> HWCSession::setPanelLuminanceAttributes(uint32_t disp_id, float pan_min_lum,
808 float pan_max_lum) {
809 // currently doing only for virtual display
810 if (disp_id != qdutils::DISPLAY_VIRTUAL) {
811 return -EINVAL;
812 }
813
814 std::lock_guard<std::mutex> obj(mutex_lum_);
815 set_min_lum_ = pan_min_lum;
816 set_max_lum_ = pan_max_lum;
817 DLOGI("set max_lum %f, min_lum %f", set_max_lum_, set_min_lum_);
818
819 return 0;
820}
821
822Return<bool> HWCSession::isBuiltInDisplay(uint32_t disp_id) {
823 if ((map_info_primary_.client_id == disp_id) && (map_info_primary_.disp_type == kBuiltIn))
824 return true;
825
826 for (auto &info : map_info_builtin_) {
827 if (disp_id == info.client_id) {
828 return true;
829 }
830 }
831
832 return false;
833}
Archit Srivastavaa59c4ff2019-05-20 10:54:22 +0530834
Dileep Marchyaafa45bc2019-06-21 17:05:31 +0530835Return<void> HWCSession::getSupportedDSIBitClks(uint32_t disp_id,
836 getSupportedDSIBitClks_cb _hidl_cb) {
837 SCOPE_LOCK(locker_[disp_id]);
838 if (!hwc_display_[disp_id]) {
839 return Void();
840 }
841
842 std::vector<uint64_t> bit_clks;
843 hwc_display_[disp_id]->GetSupportedDSIClock(&bit_clks);
844
845 hidl_vec<uint64_t> hidl_bit_clks = bit_clks;
846 _hidl_cb(hidl_bit_clks);
847
848 return Void();
849}
850
851Return<uint64_t> HWCSession::getDSIClk(uint32_t disp_id) {
852 SCOPE_LOCK(locker_[disp_id]);
853 if (!hwc_display_[disp_id]) {
854 return 0;
855 }
856
857 uint64_t bit_clk = 0;
858 hwc_display_[disp_id]->GetDynamicDSIClock(&bit_clk);
859
860 return bit_clk;
861}
862
863Return<int32_t> HWCSession::setDSIClk(uint32_t disp_id, uint64_t bit_clk) {
864 SCOPE_LOCK(locker_[disp_id]);
865 if (!hwc_display_[disp_id]) {
866 return -1;
867 }
868
869 return hwc_display_[disp_id]->SetDynamicDSIClock(bit_clk);
870}
871
Dileep Marchyacb2a3a92019-06-21 17:30:50 +0530872Return<int32_t> HWCSession::setCWBOutputBuffer(const sp<IDisplayCWBCallback> &callback,
Dileep Marchyaafa45bc2019-06-21 17:05:31 +0530873 uint32_t disp_id, const Rect &rect,
874 bool post_processed, const hidl_handle& buffer) {
Dileep Marchyacb2a3a92019-06-21 17:30:50 +0530875 if (!callback || !buffer.getNativeHandle()) {
876 DLOGE("Invalid parameters");
877 return -1;
878 }
879
880 if (disp_id != qdutils::DISPLAY_PRIMARY) {
881 DLOGE("Only supported for primary display at present.");
882 return -1;
883 }
884
885 if (rect.left || rect.top || rect.right || rect.bottom) {
886 DLOGE("Cropping rectangle is not supported.");
887 return -1;
888 }
889
890 // Mutex scope
891 {
892 SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]);
893 if (!hwc_display_[disp_id]) {
894 DLOGE("Display is not created yet.");
895 return -1;
896 }
897 }
898
899 return cwb_.PostBuffer(callback, post_processed, buffer);
Dileep Marchyaafa45bc2019-06-21 17:05:31 +0530900}
Dileep Marchyacb2a3a92019-06-21 17:30:50 +0530901
902int32_t HWCSession::CWB::PostBuffer(const sp<IDisplayCWBCallback> &callback, bool post_processed,
903 const hidl_handle& buffer) {
904 SCOPE_LOCK(queue_lock_);
905
906 // Ensure that async task runs only until all queued CWB requests have been fulfilled.
907 // If cwb queue is empty, async task has not either started or async task has finished
908 // processing previously queued cwb requests. Start new async task on such a case as
909 // currently running async task will automatically desolve without processing more requests.
910 bool post_future = !queue_.size();
911
912 QueueNode *node = new QueueNode(callback, post_processed, buffer);
913 queue_.push(node);
914
915 if (post_future) {
916 // No need to do future.get() here for previously running async task. Async method will
917 // guarantee to exit after cwb for all queued requests is indeed complete i.e. the respective
918 // fences have signaled and client is notified through registered callbacks. This will make
919 // sure that the new async task does not concurrently work with previous task. Let async running
920 // thread dissolve on its own.
921 future_ = std::async(HWCSession::CWB::AsyncTask, this);
922 }
923
924 return 0;
925}
926
927void HWCSession::CWB::ProcessRequests() {
928 HWCDisplay *hwc_display = hwc_session_->hwc_display_[HWC_DISPLAY_PRIMARY];
929 Locker &locker = hwc_session_->locker_[HWC_DISPLAY_PRIMARY];
930
931 while (true) {
932 QueueNode *node = nullptr;
933 int status = 0;
934
935 // Mutex scope
936 // Just check if there is a next cwb request queued, exit the thread if nothing is pending.
937 // Do not keep mutex locked so that client can freely queue more jobs to the current thread.
938 {
939 SCOPE_LOCK(queue_lock_);
940 if (!queue_.size()) {
941 break;
942 }
943
944 node = queue_.front();
945 }
946
947 // Configure cwb parameters, trigger refresh, wait for commit, get the release fence and
948 // wait for fence to signal.
949
950 // Mutex scope
951 // Wait for previous commit to finish before configuring next buffer.
952 {
953 SEQUENCE_WAIT_SCOPE_LOCK(locker);
954 if (hwc_display->SetReadbackBuffer(node->buffer.getNativeHandle(), -1, node->post_processed,
955 kCWBClientExternal) != HWC2::Error::None) {
956 DLOGE("CWB buffer could not be set.");
957 status = -1;
958 }
959 }
960
961 if (!status) {
Varun Aroradff7d8d2019-08-05 18:12:43 -0700962 hwc_session_->callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
Dileep Marchyacb2a3a92019-06-21 17:30:50 +0530963
964 std::unique_lock<std::mutex> lock(mutex_);
965 cv_.wait(lock);
966
967 int release_fence = -1;
968 // Mutex scope
969 {
970 SCOPE_LOCK(locker);
971 hwc_display->GetReadbackBufferFence(&release_fence);
972 }
973
974 if (release_fence >= 0) {
975 status = sync_wait(release_fence, 1000);
976 } else {
977 DLOGE("CWB release fence could not be retrieved.");
978 status = -1;
979 }
980 }
981
982 // Notify client about buffer status and erase the node from pending request queue.
983 if (!status) {
984 node->callback->onBufferReady(node->buffer);
985 } else {
986 node->callback->onBufferError(node->buffer);
987 }
988
989 delete node;
990
991 // Mutex scope
992 // Make sure to exit here, if queue becomes empty after erasing current node from queue,
993 // so that the current async task does not operate concurrently with a new future task.
994 {
995 SCOPE_LOCK(queue_lock_);
996 queue_.pop();
997
998 if (!queue_.size()) {
999 break;
1000 }
1001 }
1002 }
1003}
1004
1005void HWCSession::CWB::AsyncTask(CWB *cwb) {
1006 cwb->ProcessRequests();
1007}
1008
Dileep Marchyacb2a3a92019-06-21 17:30:50 +05301009void HWCSession::CWB::PresentDisplayDone(hwc2_display_t disp_id) {
1010 if (disp_id != HWC_DISPLAY_PRIMARY) {
1011 return;
1012 }
1013
1014 std::unique_lock<std::mutex> lock(mutex_);
1015 cv_.notify_one();
1016}
1017
Dileep Marchya6860b2b2017-04-07 15:56:47 +05301018} // namespace sdm