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