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
39using namespace android;
40using namespace qService;
41
42namespace 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
48int 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
66int 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
88int 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
105int 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
126int 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
147int 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
165int 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
183int 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
201int 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
220int 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
239DisplayAttributes 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
266int 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
284int 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
300int 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
319int setStandByMode(int mode) {
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(mode);
326        err = binder->dispatch(IQService::SET_STAND_BY_MODE,
327              &inParcel, &outParcel);
328        if(err) {
329            ALOGE("%s() failed with err %d", __FUNCTION__, err);
330        }
331    }
332    return err;
333}
334
335}// namespace
336
337// ----------------------------------------------------------------------------
338// Functions for linking dynamically to libqdutils
339// ----------------------------------------------------------------------------
340extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) {
341    status_t err = (status_t) FAILED_TRANSACTION;
342    sp<IQService> binder = getBinder();
343    Parcel inParcel, outParcel;
344    inParcel.writeInt32(dpy);
345    inParcel.writeInt32(min_enc_level);
346
347    if(binder != NULL) {
348        err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED,
349                &inParcel, &outParcel);
350    }
351
352    if(err) {
353        ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err);
354    } else {
355        err = outParcel.readInt32();
356    }
357
358    return err;
359}
360
361extern "C" int refreshScreen() {
362    int ret = 0;
363    ret = screenRefresh();
364    return ret;
365}
366
367extern "C" int controlPartialUpdate(int dpy, int mode) {
368    status_t err = (status_t) FAILED_TRANSACTION;
369    sp<IQService> binder = getBinder();
370    if(binder != NULL) {
371        Parcel inParcel, outParcel;
372        inParcel.writeInt32(dpy);
373        inParcel.writeInt32(mode);
374        err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel);
375        if(err != 0) {
376            ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err);
377        } else {
378            return outParcel.readInt32();
379        }
380    }
381
382    return err;
383}
384
385