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