1 /*
2 * Copyright (c) 2013-2014, 2016, 2018-2021, 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 /*
31 * Changes from Qualcomm Innovation Center are provided under the following license:
32 *
33 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted (subject to the limitations in the
37 * disclaimer below) provided that the following conditions are met:
38 *
39 * * Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 *
42 * * Redistributions in binary form must reproduce the above
43 * copyright notice, this list of conditions and the following
44 * disclaimer in the documentation and/or other materials provided
45 * with the distribution.
46 *
47 * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its
48 * contributors may be used to endorse or promote products derived
49 * from this software without specific prior written permission.
50 *
51 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
52 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
53 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
54 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
55 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
57 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
59 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
61 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
62 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
63 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 */
65
66 #include <fcntl.h>
67 #include <stdio.h>
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #include <unistd.h>
71 #include <display_config.h>
72 #include <QServiceUtils.h>
73 #include <qd_utils.h>
74
75 using namespace android;
76 using namespace qService;
77
78 namespace qdutils {
79
80 //=============================================================================
81 // The functions below run in the client process and wherever necessary
82 // do a binder call to HWC to get/set data.
83
isExternalConnected(void)84 int isExternalConnected(void) {
85 return FAILED_TRANSACTION;
86 }
87
getDisplayAttributes(int,DisplayAttributes_t &)88 int getDisplayAttributes(int /* dpy */, DisplayAttributes_t& /* dpyattr */) {
89 return FAILED_TRANSACTION;
90 }
91
getDisplayVisibleRegion(int dpy,hwc_rect_t & rect)92 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
93 status_t err = (status_t) FAILED_TRANSACTION;
94 sp<IQService> binder = getBinder();
95 Parcel inParcel, outParcel;
96 inParcel.writeInt32(dpy);
97 if(binder != NULL) {
98 err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
99 &inParcel, &outParcel);
100 }
101 if(!err) {
102 rect.left = outParcel.readInt32();
103 rect.top = outParcel.readInt32();
104 rect.right = outParcel.readInt32();
105 rect.bottom = outParcel.readInt32();
106 } else {
107 ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
108 __FUNCTION__, dpy, err);
109 }
110 return err;
111 }
112
setViewFrame(int,int,int,int,int)113 int setViewFrame(int /* dpy */, int /* l */, int /* t */, int /* r */, int /* b */) {
114 return FAILED_TRANSACTION;
115 }
116
setSecondaryDisplayStatus(int dpy,uint32_t status)117 int setSecondaryDisplayStatus(int dpy, uint32_t status) {
118 status_t err = (status_t) FAILED_TRANSACTION;
119 sp<IQService> binder = getBinder();
120 Parcel inParcel, outParcel;
121 inParcel.writeInt32(dpy);
122 inParcel.writeInt32(status);
123
124 if(binder != NULL) {
125 err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
126 &inParcel, &outParcel);
127 }
128 if(err)
129 ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
130 status, err);
131
132 return err;
133 }
134
configureDynRefreshRate(uint32_t op,uint32_t refreshRate)135 int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
136 status_t err = (status_t) FAILED_TRANSACTION;
137 sp<IQService> binder = getBinder();
138 Parcel inParcel, outParcel;
139 inParcel.writeInt32(op);
140 inParcel.writeInt32(refreshRate);
141
142 if(binder != NULL) {
143 err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
144 &inParcel, &outParcel);
145 }
146
147 if(err)
148 ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
149
150 return err;
151 }
152
getConfigCount(int)153 int getConfigCount(int /*dpy*/) {
154 int numConfigs = -1;
155 sp<IQService> binder = getBinder();
156 if(binder != NULL) {
157 Parcel inParcel, outParcel;
158 inParcel.writeInt32(DISPLAY_PRIMARY);
159 status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
160 &inParcel, &outParcel);
161 if(!err) {
162 numConfigs = outParcel.readInt32();
163 ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
164 } else {
165 ALOGE("%s() failed with err %d", __FUNCTION__, err);
166 }
167 }
168 return numConfigs;
169 }
170
getActiveConfig(int dpy)171 int getActiveConfig(int dpy) {
172 int configIndex = -1;
173 sp<IQService> binder = getBinder();
174 if(binder != NULL) {
175 Parcel inParcel, outParcel;
176 inParcel.writeInt32(dpy);
177 status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
178 &inParcel, &outParcel);
179 if(!err) {
180 configIndex = outParcel.readInt32();
181 ALOGI("%s() Received active config index %d", __FUNCTION__,
182 configIndex);
183 } else {
184 ALOGE("%s() failed with err %d", __FUNCTION__, err);
185 }
186 }
187 return configIndex;
188 }
189
setActiveConfig(int configIndex,int)190 int setActiveConfig(int configIndex, int /*dpy*/) {
191 status_t err = (status_t) FAILED_TRANSACTION;
192 sp<IQService> binder = getBinder();
193 if(binder != NULL) {
194 Parcel inParcel, outParcel;
195 inParcel.writeInt32(configIndex);
196 inParcel.writeInt32(DISPLAY_PRIMARY);
197 err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
198 &inParcel, &outParcel);
199 if(!err) {
200 ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
201 configIndex);
202 } else {
203 ALOGE("%s() failed with err %d", __FUNCTION__, err);
204 }
205 }
206 return err;
207 }
208
getDisplayAttributes(int configIndex,int dpy)209 DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
210 DisplayAttributes dpyattr = {};
211 sp<IQService> binder = getBinder();
212 if(binder != NULL) {
213 Parcel inParcel, outParcel;
214 inParcel.writeInt32(configIndex);
215 inParcel.writeInt32(dpy);
216 status_t err = binder->dispatch(
217 IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
218 &outParcel);
219 if(!err) {
220 dpyattr.vsync_period = outParcel.readInt32();
221 dpyattr.xres = outParcel.readInt32();
222 dpyattr.yres = outParcel.readInt32();
223 dpyattr.xdpi = outParcel.readFloat();
224 dpyattr.ydpi = outParcel.readFloat();
225 dpyattr.panel_type = outParcel.readInt32();
226 dpyattr.is_yuv = outParcel.readInt32();
227 ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
228 __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
229 } else {
230 ALOGE("%s() failed with err %d", __FUNCTION__, err);
231 }
232 }
233 return dpyattr;
234 }
235
setPanelMode(int mode)236 int setPanelMode(int mode) {
237 status_t err = (status_t) FAILED_TRANSACTION;
238 sp<IQService> binder = getBinder();
239 if(binder != NULL) {
240 Parcel inParcel, outParcel;
241 inParcel.writeInt32(mode);
242 err = binder->dispatch(IQService::SET_DISPLAY_MODE,
243 &inParcel, &outParcel);
244 if(!err) {
245 ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
246 mode);
247 } else {
248 ALOGE("%s() failed with err %d", __FUNCTION__, err);
249 }
250 }
251 return err;
252 }
253
setPanelBrightness(int level)254 int setPanelBrightness(int level) {
255 status_t err = (status_t) FAILED_TRANSACTION;
256 sp<IQService> binder = getBinder();
257 Parcel inParcel, outParcel;
258
259 if(binder != NULL) {
260 inParcel.writeInt32(level);
261 status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
262 &inParcel, &outParcel);
263 if(err) {
264 ALOGE("%s() failed with err %d", __FUNCTION__, err);
265 }
266 }
267 return err;
268 }
269
getPanelBrightness()270 int getPanelBrightness() {
271 int panel_brightness = -1;
272 sp<IQService> binder = getBinder();
273 Parcel inParcel, outParcel;
274
275 if(binder != NULL) {
276 status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
277 &inParcel, &outParcel);
278 if(!err) {
279 panel_brightness = outParcel.readInt32();
280 ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
281 panel_brightness);
282 } else {
283 ALOGE("%s() failed with err %d", __FUNCTION__, err);
284 }
285 }
286 return panel_brightness;
287 }
288
setDsiClk(int dpy,uint64_t bitClk)289 int setDsiClk(int dpy, uint64_t bitClk) {
290 status_t err = (status_t) FAILED_TRANSACTION;
291 sp<IQService> binder = getBinder();
292 Parcel inParcel, outParcel;
293
294 if(binder != NULL) {
295 inParcel.writeInt32(dpy);
296 inParcel.writeUint64(bitClk);
297 status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel);
298 if(err) {
299 ALOGE("%s() failed with err %d", __FUNCTION__, err);
300 }
301 }
302 return err;
303 }
304
getDsiClk(int dpy)305 uint64_t getDsiClk(int dpy) {
306 uint64_t dsi_clk = 0;
307 sp<IQService> binder = getBinder();
308 Parcel inParcel, outParcel;
309
310 if(binder != NULL) {
311 inParcel.writeInt32(dpy);
312 status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel);
313 if(!err) {
314 dsi_clk = outParcel.readUint64();
315 } else {
316 ALOGE("%s() failed with err %d", __FUNCTION__, err);
317 }
318 }
319 return dsi_clk;
320 }
321
getSupportedBitClk(int dpy,std::vector<uint64_t> & bit_rates)322 int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) {
323 sp<IQService> binder = getBinder();
324 Parcel inParcel, outParcel;
325
326 if(binder != NULL) {
327 inParcel.writeInt32(dpy);
328 status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel);
329 if(err) {
330 ALOGE("%s() failed with err %d", __FUNCTION__, err);
331 return err;
332 }
333 }
334
335 int32_t clk_levels = outParcel.readInt32();
336 while (clk_levels > 0) {
337 bit_rates.push_back(outParcel.readUint64());
338 clk_levels--;
339 }
340 return 0;
341 }
342
setPanelLuminanceAttributes(int dpy,float min_lum,float max_lum)343 int setPanelLuminanceAttributes(int dpy, float min_lum, float max_lum) {
344 status_t err = (status_t) FAILED_TRANSACTION;
345 sp<IQService> binder = getBinder();
346 Parcel inParcel, outParcel;
347
348 if(binder != NULL) {
349 inParcel.writeInt32(dpy);
350 inParcel.writeFloat(min_lum);
351 inParcel.writeFloat(max_lum);
352 status_t err = binder->dispatch(IQService::SET_PANEL_LUMINANCE, &inParcel, &outParcel);
353 if(err) {
354 ALOGE("%s() failed with err %d", __FUNCTION__, err);
355 }
356 }
357 return err;
358 }
359
360 }// namespace
361
362 // ----------------------------------------------------------------------------
363 // Functions for linking dynamically to libqdutils
364 // ----------------------------------------------------------------------------
minHdcpEncryptionLevelChanged(int dpy,int min_enc_level)365 extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
366 status_t err = (status_t) FAILED_TRANSACTION;
367 sp<IQService> binder = getBinder();
368 Parcel inParcel, outParcel;
369 inParcel.writeInt32(dpy);
370 inParcel.writeInt32(min_enc_level);
371
372 if(binder != NULL) {
373 err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
374 &inParcel, &outParcel);
375 }
376
377 if(err) {
378 ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
379 } else {
380 err = outParcel.readInt32();
381 }
382
383 return err;
384 }
385
refreshScreen(int dpy)386 extern "C" int refreshScreen(int dpy) {
387 int ret = 0;
388 ret = screenRefresh(dpy);
389 return ret;
390 }
391
controlPartialUpdate(int dpy,int mode)392 extern "C" int controlPartialUpdate(int dpy, int mode) {
393 status_t err = (status_t) FAILED_TRANSACTION;
394 sp<IQService> binder = getBinder();
395 if(binder != NULL) {
396 Parcel inParcel, outParcel;
397 inParcel.writeInt32(dpy);
398 inParcel.writeInt32(mode);
399 err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
400 if(err != 0) {
401 ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
402 } else {
403 return outParcel.readInt32();
404 }
405 }
406
407 return err;
408 }
409
410 // returns 0 if composer is up
waitForComposerInit()411 extern "C" int waitForComposerInit() {
412 int status = false;
413 sp<IQService> binder = getBinder();
414 if (binder == NULL) {
415 sleep(2);
416 binder = getBinder();
417 }
418
419 if (binder != NULL) {
420 Parcel inParcel, outParcel;
421 binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
422 status = !!outParcel.readInt32();
423 if (!status) {
424 sleep(2);
425 binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
426 status = !!outParcel.readInt32();
427 }
428 }
429
430 return !status;
431 }
432
setStandByMode(int mode,int is_twm=false)433 extern "C" int setStandByMode(int mode, int is_twm = false) {
434 status_t err = (status_t) FAILED_TRANSACTION;
435 sp<IQService> binder = getBinder();
436 Parcel inParcel, outParcel;
437
438 if(binder != NULL) {
439 inParcel.writeInt32(mode);
440 inParcel.writeInt32(is_twm);
441 err = binder->dispatch(IQService::SET_STAND_BY_MODE,
442 &inParcel, &outParcel);
443 if(err) {
444 ALOGE("%s() failed with err %d", __FUNCTION__, err);
445 }
446 }
447 return err;
448 }
449
getPanelResolution(int * width,int * height)450 extern "C" int getPanelResolution(int *width, int *height) {
451 status_t err = (status_t) FAILED_TRANSACTION;
452 sp<IQService> binder = getBinder();
453 Parcel inParcel, outParcel;
454
455 if(binder != NULL) {
456 err = binder->dispatch(IQService::GET_PANEL_RESOLUTION,
457 &inParcel, &outParcel);
458 if(err != 0) {
459 ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
460 } else {
461 *width = outParcel.readInt32();
462 *height = outParcel.readInt32();
463 }
464 }
465
466 return err;
467 }
468
delayFirstCommit(void)469 extern "C" int delayFirstCommit(void) {
470 status_t err = (status_t) FAILED_TRANSACTION;
471 sp<IQService> binder = getBinder();
472 if(binder != NULL) {
473 err = binder->dispatch(IQService::DELAY_FIRST_COMMIT, NULL, NULL);
474 if(err) {
475 ALOGE("%s() failed with err %d", __FUNCTION__, err);
476 }
477 }
478 return err;
479 }
480