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