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 #include <fcntl.h>
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
35 #include <display_config.h>
36 #include <QServiceUtils.h>
37 #include <qd_utils.h>
38 
39 using namespace android;
40 using namespace qService;
41 
42 namespace qdutils {
43 
44 //=============================================================================
45 // The functions below run in the client process and wherever necessary
46 // do a binder call to HWC to get/set data.
47 
isExternalConnected(void)48 int isExternalConnected(void) {
49     return FAILED_TRANSACTION;
50 }
51 
getDisplayAttributes(int,DisplayAttributes_t &)52 int getDisplayAttributes(int /* dpy */, DisplayAttributes_t& /* dpyattr */) {
53     return FAILED_TRANSACTION;
54 }
55 
getDisplayVisibleRegion(int dpy,hwc_rect_t & rect)56 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
57     status_t err = (status_t) FAILED_TRANSACTION;
58     sp<IQService> binder = getBinder();
59     Parcel inParcel, outParcel;
60     inParcel.writeInt32(dpy);
61     if(binder != NULL) {
62         err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
63                 &inParcel, &outParcel);
64     }
65     if(!err) {
66         rect.left = outParcel.readInt32();
67         rect.top = outParcel.readInt32();
68         rect.right = outParcel.readInt32();
69         rect.bottom = outParcel.readInt32();
70     } else {
71         ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
72               __FUNCTION__, dpy, err);
73     }
74     return err;
75 }
76 
setViewFrame(int,int,int,int,int)77 int setViewFrame(int /* dpy */, int /* l */, int /* t */, int /* r */, int /* b */) {
78     return FAILED_TRANSACTION;
79 }
80 
setSecondaryDisplayStatus(int dpy,uint32_t status)81 int setSecondaryDisplayStatus(int dpy, uint32_t status) {
82     status_t err = (status_t) FAILED_TRANSACTION;
83     sp<IQService> binder = getBinder();
84     Parcel inParcel, outParcel;
85     inParcel.writeInt32(dpy);
86     inParcel.writeInt32(status);
87 
88     if(binder != NULL) {
89         err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
90                 &inParcel, &outParcel);
91     }
92     if(err)
93         ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
94                                                         status, err);
95 
96     return err;
97 }
98 
configureDynRefreshRate(uint32_t op,uint32_t refreshRate)99 int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
100     status_t err = (status_t) FAILED_TRANSACTION;
101     sp<IQService> binder = getBinder();
102     Parcel inParcel, outParcel;
103     inParcel.writeInt32(op);
104     inParcel.writeInt32(refreshRate);
105 
106     if(binder != NULL) {
107         err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
108                                &inParcel, &outParcel);
109     }
110 
111     if(err)
112         ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
113 
114     return err;
115 }
116 
getConfigCount(int)117 int getConfigCount(int /*dpy*/) {
118     int numConfigs = -1;
119     sp<IQService> binder = getBinder();
120     if(binder != NULL) {
121         Parcel inParcel, outParcel;
122         inParcel.writeInt32(DISPLAY_PRIMARY);
123         status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
124                 &inParcel, &outParcel);
125         if(!err) {
126             numConfigs = outParcel.readInt32();
127             ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
128         } else {
129             ALOGE("%s() failed with err %d", __FUNCTION__, err);
130         }
131     }
132     return numConfigs;
133 }
134 
getActiveConfig(int dpy)135 int getActiveConfig(int dpy) {
136     int configIndex = -1;
137     sp<IQService> binder = getBinder();
138     if(binder != NULL) {
139         Parcel inParcel, outParcel;
140         inParcel.writeInt32(dpy);
141         status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
142                 &inParcel, &outParcel);
143         if(!err) {
144             configIndex = outParcel.readInt32();
145             ALOGI("%s() Received active config index %d", __FUNCTION__,
146                     configIndex);
147         } else {
148             ALOGE("%s() failed with err %d", __FUNCTION__, err);
149         }
150     }
151     return configIndex;
152 }
153 
setActiveConfig(int configIndex,int)154 int setActiveConfig(int configIndex, int /*dpy*/) {
155     status_t err = (status_t) FAILED_TRANSACTION;
156     sp<IQService> binder = getBinder();
157     if(binder != NULL) {
158         Parcel inParcel, outParcel;
159         inParcel.writeInt32(configIndex);
160         inParcel.writeInt32(DISPLAY_PRIMARY);
161         err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
162                 &inParcel, &outParcel);
163         if(!err) {
164             ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
165                     configIndex);
166         } else {
167             ALOGE("%s() failed with err %d", __FUNCTION__, err);
168         }
169     }
170     return err;
171 }
172 
getDisplayAttributes(int configIndex,int dpy)173 DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
174     DisplayAttributes dpyattr = {};
175     sp<IQService> binder = getBinder();
176     if(binder != NULL) {
177         Parcel inParcel, outParcel;
178         inParcel.writeInt32(configIndex);
179         inParcel.writeInt32(dpy);
180         status_t err = binder->dispatch(
181                 IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
182                 &outParcel);
183         if(!err) {
184             dpyattr.vsync_period = outParcel.readInt32();
185             dpyattr.xres = outParcel.readInt32();
186             dpyattr.yres = outParcel.readInt32();
187             dpyattr.xdpi = outParcel.readFloat();
188             dpyattr.ydpi = outParcel.readFloat();
189             dpyattr.panel_type = outParcel.readInt32();
190             dpyattr.is_yuv = outParcel.readInt32();
191             ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
192                     __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
193         } else {
194             ALOGE("%s() failed with err %d", __FUNCTION__, err);
195         }
196     }
197     return dpyattr;
198 }
199 
setPanelMode(int mode)200 int setPanelMode(int mode) {
201     status_t err = (status_t) FAILED_TRANSACTION;
202     sp<IQService> binder = getBinder();
203     if(binder != NULL) {
204         Parcel inParcel, outParcel;
205         inParcel.writeInt32(mode);
206         err = binder->dispatch(IQService::SET_DISPLAY_MODE,
207                                &inParcel, &outParcel);
208         if(!err) {
209             ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
210                   mode);
211         } else {
212             ALOGE("%s() failed with err %d", __FUNCTION__, err);
213         }
214     }
215     return err;
216 }
217 
setPanelBrightness(int level)218 int setPanelBrightness(int level) {
219     status_t err = (status_t) FAILED_TRANSACTION;
220     sp<IQService> binder = getBinder();
221     Parcel inParcel, outParcel;
222 
223     if(binder != NULL) {
224         inParcel.writeInt32(level);
225         status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
226                 &inParcel, &outParcel);
227         if(err) {
228             ALOGE("%s() failed with err %d", __FUNCTION__, err);
229         }
230     }
231     return err;
232 }
233 
getPanelBrightness()234 int getPanelBrightness() {
235     int panel_brightness = -1;
236     sp<IQService> binder = getBinder();
237     Parcel inParcel, outParcel;
238 
239     if(binder != NULL) {
240         status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
241                 &inParcel, &outParcel);
242         if(!err) {
243             panel_brightness = outParcel.readInt32();
244             ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
245                     panel_brightness);
246         } else {
247             ALOGE("%s() failed with err %d", __FUNCTION__, err);
248         }
249     }
250     return panel_brightness;
251 }
252 
setDsiClk(int dpy,uint64_t bitClk)253 int setDsiClk(int dpy, uint64_t bitClk) {
254     status_t err = (status_t) FAILED_TRANSACTION;
255     sp<IQService> binder = getBinder();
256     Parcel inParcel, outParcel;
257 
258     if(binder != NULL) {
259         inParcel.writeInt32(dpy);
260         inParcel.writeUint64(bitClk);
261         status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel);
262         if(err) {
263             ALOGE("%s() failed with err %d", __FUNCTION__, err);
264         }
265     }
266     return err;
267 }
268 
getDsiClk(int dpy)269 uint64_t getDsiClk(int dpy) {
270     uint64_t dsi_clk = 0;
271     sp<IQService> binder = getBinder();
272     Parcel inParcel, outParcel;
273 
274     if(binder != NULL) {
275         inParcel.writeInt32(dpy);
276         status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel);
277         if(!err) {
278             dsi_clk = outParcel.readUint64();
279         } else {
280             ALOGE("%s() failed with err %d", __FUNCTION__, err);
281         }
282     }
283     return dsi_clk;
284 }
285 
getSupportedBitClk(int dpy,std::vector<uint64_t> & bit_rates)286 int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) {
287     sp<IQService> binder = getBinder();
288     Parcel inParcel, outParcel;
289 
290     if(binder != NULL) {
291         inParcel.writeInt32(dpy);
292         status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel);
293         if(err) {
294             ALOGE("%s() failed with err %d", __FUNCTION__, err);
295             return err;
296         }
297     }
298 
299     int32_t clk_levels = outParcel.readInt32();
300     while (clk_levels > 0) {
301       bit_rates.push_back(outParcel.readUint64());
302       clk_levels--;
303     }
304     return 0;
305 }
306 
setPanelLuminanceAttributes(int dpy,float min_lum,float max_lum)307 int setPanelLuminanceAttributes(int dpy, float min_lum, float max_lum) {
308     status_t err = (status_t) FAILED_TRANSACTION;
309     sp<IQService> binder = getBinder();
310     Parcel inParcel, outParcel;
311 
312     if(binder != NULL) {
313         inParcel.writeInt32(dpy);
314         inParcel.writeFloat(min_lum);
315         inParcel.writeFloat(max_lum);
316         status_t err = binder->dispatch(IQService::SET_PANEL_LUMINANCE, &inParcel, &outParcel);
317         if(err) {
318             ALOGE("%s() failed with err %d", __FUNCTION__, err);
319         }
320     }
321     return err;
322 }
323 
324 }// namespace
325 
326 // ----------------------------------------------------------------------------
327 // Functions for linking dynamically to libqdutils
328 // ----------------------------------------------------------------------------
minHdcpEncryptionLevelChanged(int dpy,int min_enc_level)329 extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
330     status_t err = (status_t) FAILED_TRANSACTION;
331     sp<IQService> binder = getBinder();
332     Parcel inParcel, outParcel;
333     inParcel.writeInt32(dpy);
334     inParcel.writeInt32(min_enc_level);
335 
336     if(binder != NULL) {
337         err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
338                 &inParcel, &outParcel);
339     }
340 
341     if(err) {
342         ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
343     } else {
344         err = outParcel.readInt32();
345     }
346 
347     return err;
348 }
349 
refreshScreen(int dpy)350 extern "C" int refreshScreen(int dpy) {
351     int ret = 0;
352     ret = screenRefresh(dpy);
353     return ret;
354 }
355 
controlPartialUpdate(int dpy,int mode)356 extern "C" int controlPartialUpdate(int dpy, int mode) {
357     status_t err = (status_t) FAILED_TRANSACTION;
358     sp<IQService> binder = getBinder();
359     if(binder != NULL) {
360         Parcel inParcel, outParcel;
361         inParcel.writeInt32(dpy);
362         inParcel.writeInt32(mode);
363         err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
364         if(err != 0) {
365             ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
366         } else {
367             return outParcel.readInt32();
368         }
369     }
370 
371     return err;
372 }
373 
374 // returns 0 if composer is up
waitForComposerInit()375 extern "C" int waitForComposerInit() {
376     int status = false;
377     sp<IQService> binder = getBinder();
378     if (binder == NULL) {
379         sleep(2);
380         binder = getBinder();
381     }
382 
383     if (binder != NULL) {
384         Parcel inParcel, outParcel;
385         binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
386         status = !!outParcel.readInt32();
387         if (!status) {
388             sleep(2);
389             binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel);
390             status = !!outParcel.readInt32();
391         }
392     }
393 
394     return !status;
395 }
396 
setStandByMode(int mode)397 extern "C" int setStandByMode(int mode) {
398     status_t err = (status_t) FAILED_TRANSACTION;
399     sp<IQService> binder = getBinder();
400     Parcel inParcel, outParcel;
401 
402     if(binder != NULL) {
403         inParcel.writeInt32(mode);
404         err = binder->dispatch(IQService::SET_STAND_BY_MODE,
405               &inParcel, &outParcel);
406         if(err) {
407             ALOGE("%s() failed with err %d", __FUNCTION__, err);
408         }
409     }
410     return err;
411 }
412