1 /*
2 * Copyright (c) 2013-2014, 2016, 2018, 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 
setHSIC(int dpy,const HSICData_t & hsic_data)88 int setHSIC(int dpy, const HSICData_t& hsic_data) {
89     status_t err = (status_t) FAILED_TRANSACTION;
90     sp<IQService> binder = getBinder();
91     Parcel inParcel, outParcel;
92     inParcel.writeInt32(dpy);
93     inParcel.writeInt32(hsic_data.hue);
94     inParcel.writeFloat(hsic_data.saturation);
95     inParcel.writeInt32(hsic_data.intensity);
96     inParcel.writeFloat(hsic_data.contrast);
97     if(binder != NULL) {
98         err = binder->dispatch(IQService::SET_HSIC_DATA, &inParcel, &outParcel);
99     }
100     if(err)
101         ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
102     return err;
103 }
104 
getDisplayVisibleRegion(int dpy,hwc_rect_t & rect)105 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
106     status_t err = (status_t) FAILED_TRANSACTION;
107     sp<IQService> binder = getBinder();
108     Parcel inParcel, outParcel;
109     inParcel.writeInt32(dpy);
110     if(binder != NULL) {
111         err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
112                 &inParcel, &outParcel);
113     }
114     if(!err) {
115         rect.left = outParcel.readInt32();
116         rect.top = outParcel.readInt32();
117         rect.right = outParcel.readInt32();
118         rect.bottom = outParcel.readInt32();
119     } else {
120         ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
121               __FUNCTION__, dpy, err);
122     }
123     return err;
124 }
125 
setViewFrame(int dpy,int l,int t,int r,int b)126 int setViewFrame(int dpy, int l, int t, int r, int b) {
127     status_t err = (status_t) FAILED_TRANSACTION;
128     sp<IQService> binder = getBinder();
129     Parcel inParcel, outParcel;
130     inParcel.writeInt32(dpy);
131     inParcel.writeInt32(l);
132     inParcel.writeInt32(t);
133     inParcel.writeInt32(r);
134     inParcel.writeInt32(b);
135 
136     if(binder != NULL) {
137         err = binder->dispatch(IQService::SET_VIEW_FRAME,
138                 &inParcel, &outParcel);
139     }
140     if(err)
141         ALOGE("%s: Failed to set view frame for dpy %d err=%d",
142                             __FUNCTION__, dpy, err);
143 
144     return err;
145 }
146 
setSecondaryDisplayStatus(int dpy,uint32_t status)147 int setSecondaryDisplayStatus(int dpy, uint32_t status) {
148     status_t err = (status_t) FAILED_TRANSACTION;
149     sp<IQService> binder = getBinder();
150     Parcel inParcel, outParcel;
151     inParcel.writeInt32(dpy);
152     inParcel.writeInt32(status);
153 
154     if(binder != NULL) {
155         err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS,
156                 &inParcel, &outParcel);
157     }
158     if(err)
159         ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy,
160                                                         status, err);
161 
162     return err;
163 }
164 
configureDynRefreshRate(uint32_t op,uint32_t refreshRate)165 int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) {
166     status_t err = (status_t) FAILED_TRANSACTION;
167     sp<IQService> binder = getBinder();
168     Parcel inParcel, outParcel;
169     inParcel.writeInt32(op);
170     inParcel.writeInt32(refreshRate);
171 
172     if(binder != NULL) {
173         err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE,
174                                &inParcel, &outParcel);
175     }
176 
177     if(err)
178         ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err);
179 
180     return err;
181 }
182 
getConfigCount(int)183 int getConfigCount(int /*dpy*/) {
184     int numConfigs = -1;
185     sp<IQService> binder = getBinder();
186     if(binder != NULL) {
187         Parcel inParcel, outParcel;
188         inParcel.writeInt32(DISPLAY_PRIMARY);
189         status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT,
190                 &inParcel, &outParcel);
191         if(!err) {
192             numConfigs = outParcel.readInt32();
193             ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs);
194         } else {
195             ALOGE("%s() failed with err %d", __FUNCTION__, err);
196         }
197     }
198     return numConfigs;
199 }
200 
getActiveConfig(int dpy)201 int getActiveConfig(int dpy) {
202     int configIndex = -1;
203     sp<IQService> binder = getBinder();
204     if(binder != NULL) {
205         Parcel inParcel, outParcel;
206         inParcel.writeInt32(dpy);
207         status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG,
208                 &inParcel, &outParcel);
209         if(!err) {
210             configIndex = outParcel.readInt32();
211             ALOGI("%s() Received active config index %d", __FUNCTION__,
212                     configIndex);
213         } else {
214             ALOGE("%s() failed with err %d", __FUNCTION__, err);
215         }
216     }
217     return configIndex;
218 }
219 
setActiveConfig(int configIndex,int)220 int setActiveConfig(int configIndex, int /*dpy*/) {
221     status_t err = (status_t) FAILED_TRANSACTION;
222     sp<IQService> binder = getBinder();
223     if(binder != NULL) {
224         Parcel inParcel, outParcel;
225         inParcel.writeInt32(configIndex);
226         inParcel.writeInt32(DISPLAY_PRIMARY);
227         err = binder->dispatch(IQService::SET_ACTIVE_CONFIG,
228                 &inParcel, &outParcel);
229         if(!err) {
230             ALOGI("%s() Successfully set active config index %d", __FUNCTION__,
231                     configIndex);
232         } else {
233             ALOGE("%s() failed with err %d", __FUNCTION__, err);
234         }
235     }
236     return err;
237 }
238 
getDisplayAttributes(int configIndex,int dpy)239 DisplayAttributes getDisplayAttributes(int configIndex, int dpy) {
240     DisplayAttributes dpyattr = {};
241     sp<IQService> binder = getBinder();
242     if(binder != NULL) {
243         Parcel inParcel, outParcel;
244         inParcel.writeInt32(configIndex);
245         inParcel.writeInt32(dpy);
246         status_t err = binder->dispatch(
247                 IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel,
248                 &outParcel);
249         if(!err) {
250             dpyattr.vsync_period = outParcel.readInt32();
251             dpyattr.xres = outParcel.readInt32();
252             dpyattr.yres = outParcel.readInt32();
253             dpyattr.xdpi = outParcel.readFloat();
254             dpyattr.ydpi = outParcel.readFloat();
255             dpyattr.panel_type = outParcel.readInt32();
256             dpyattr.is_yuv = outParcel.readInt32();
257             ALOGI("%s() Received attrs for index %d: xres %d, yres %d",
258                     __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres);
259         } else {
260             ALOGE("%s() failed with err %d", __FUNCTION__, err);
261         }
262     }
263     return dpyattr;
264 }
265 
setPanelMode(int mode)266 int setPanelMode(int mode) {
267     status_t err = (status_t) FAILED_TRANSACTION;
268     sp<IQService> binder = getBinder();
269     if(binder != NULL) {
270         Parcel inParcel, outParcel;
271         inParcel.writeInt32(mode);
272         err = binder->dispatch(IQService::SET_DISPLAY_MODE,
273                                &inParcel, &outParcel);
274         if(!err) {
275             ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__,
276                   mode);
277         } else {
278             ALOGE("%s() failed with err %d", __FUNCTION__, err);
279         }
280     }
281     return err;
282 }
283 
setPanelBrightness(int level)284 int setPanelBrightness(int level) {
285     status_t err = (status_t) FAILED_TRANSACTION;
286     sp<IQService> binder = getBinder();
287     Parcel inParcel, outParcel;
288 
289     if(binder != NULL) {
290         inParcel.writeInt32(level);
291         status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS,
292                 &inParcel, &outParcel);
293         if(err) {
294             ALOGE("%s() failed with err %d", __FUNCTION__, err);
295         }
296     }
297     return err;
298 }
299 
getPanelBrightness()300 int getPanelBrightness() {
301     int panel_brightness = -1;
302     sp<IQService> binder = getBinder();
303     Parcel inParcel, outParcel;
304 
305     if(binder != NULL) {
306         status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS,
307                 &inParcel, &outParcel);
308         if(!err) {
309             panel_brightness = outParcel.readInt32();
310             ALOGI("%s() Current panel brightness value %d", __FUNCTION__,
311                     panel_brightness);
312         } else {
313             ALOGE("%s() failed with err %d", __FUNCTION__, err);
314         }
315     }
316     return panel_brightness;
317 }
318 
setDsiClk(int dpy,uint64_t bitClk)319 int setDsiClk(int dpy, uint64_t bitClk) {
320     status_t err = (status_t) FAILED_TRANSACTION;
321     sp<IQService> binder = getBinder();
322     Parcel inParcel, outParcel;
323 
324     if(binder != NULL) {
325         inParcel.writeInt32(dpy);
326         inParcel.writeUint64(bitClk);
327         status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel);
328         if(err) {
329             ALOGE("%s() failed with err %d", __FUNCTION__, err);
330         }
331     }
332     return err;
333 }
334 
getDsiClk(int dpy)335 uint64_t getDsiClk(int dpy) {
336     uint64_t dsi_clk = 0;
337     sp<IQService> binder = getBinder();
338     Parcel inParcel, outParcel;
339 
340     if(binder != NULL) {
341         inParcel.writeInt32(dpy);
342         status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel);
343         if(!err) {
344             dsi_clk = outParcel.readUint64();
345         } else {
346             ALOGE("%s() failed with err %d", __FUNCTION__, err);
347         }
348     }
349     return dsi_clk;
350 }
351 
getSupportedBitClk(int dpy,std::vector<uint64_t> & bit_rates)352 int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) {
353     sp<IQService> binder = getBinder();
354     Parcel inParcel, outParcel;
355 
356     if(binder != NULL) {
357         inParcel.writeInt32(dpy);
358         status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel);
359         if(err) {
360             ALOGE("%s() failed with err %d", __FUNCTION__, err);
361             return err;
362         }
363     }
364 
365     int32_t clk_levels = outParcel.readInt32();
366     while (clk_levels > 0) {
367       bit_rates.push_back(outParcel.readUint64());
368       clk_levels--;
369     }
370     return 0;
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