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