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