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 /* 31 * Changes from Qualcomm Innovation Center are provided under the following license: 32 * 33 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted (subject to the limitations in the 37 * disclaimer below) provided that the following conditions are met: 38 * 39 * * Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 42 * * Redistributions in binary form must reproduce the above 43 * copyright notice, this list of conditions and the following 44 * disclaimer in the documentation and/or other materials provided 45 * with the distribution. 46 * 47 * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its 48 * contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE 52 * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 53 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 54 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 55 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 56 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 57 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 59 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 61 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 62 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 63 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 */ 65 66 #include <fcntl.h> 67 #include <stdio.h> 68 #include <sys/types.h> 69 #include <sys/stat.h> 70 #include <unistd.h> 71 #include <display_config.h> 72 #include <QServiceUtils.h> 73 #include <qd_utils.h> 74 75 using namespace android; 76 using namespace qService; 77 78 namespace qdutils { 79 80 //============================================================================= 81 // The functions below run in the client process and wherever necessary 82 // do a binder call to HWC to get/set data. 83 isExternalConnected(void)84 int isExternalConnected(void) { 85 return FAILED_TRANSACTION; 86 } 87 getDisplayAttributes(int,DisplayAttributes_t &)88 int getDisplayAttributes(int /* dpy */, DisplayAttributes_t& /* dpyattr */) { 89 return FAILED_TRANSACTION; 90 } 91 getDisplayVisibleRegion(int dpy,hwc_rect_t & rect)92 int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) { 93 status_t err = (status_t) FAILED_TRANSACTION; 94 sp<IQService> binder = getBinder(); 95 Parcel inParcel, outParcel; 96 inParcel.writeInt32(dpy); 97 if(binder != NULL) { 98 err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION, 99 &inParcel, &outParcel); 100 } 101 if(!err) { 102 rect.left = outParcel.readInt32(); 103 rect.top = outParcel.readInt32(); 104 rect.right = outParcel.readInt32(); 105 rect.bottom = outParcel.readInt32(); 106 } else { 107 ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d", 108 __FUNCTION__, dpy, err); 109 } 110 return err; 111 } 112 setViewFrame(int,int,int,int,int)113 int setViewFrame(int /* dpy */, int /* l */, int /* t */, int /* r */, int /* b */) { 114 return FAILED_TRANSACTION; 115 } 116 setSecondaryDisplayStatus(int dpy,uint32_t status)117 int setSecondaryDisplayStatus(int dpy, uint32_t status) { 118 status_t err = (status_t) FAILED_TRANSACTION; 119 sp<IQService> binder = getBinder(); 120 Parcel inParcel, outParcel; 121 inParcel.writeInt32(dpy); 122 inParcel.writeInt32(status); 123 124 if(binder != NULL) { 125 err = binder->dispatch(IQService::SET_SECONDARY_DISPLAY_STATUS, 126 &inParcel, &outParcel); 127 } 128 if(err) 129 ALOGE("%s: Failed for dpy %d status = %d err=%d", __FUNCTION__, dpy, 130 status, err); 131 132 return err; 133 } 134 configureDynRefreshRate(uint32_t op,uint32_t refreshRate)135 int configureDynRefreshRate(uint32_t op, uint32_t refreshRate) { 136 status_t err = (status_t) FAILED_TRANSACTION; 137 sp<IQService> binder = getBinder(); 138 Parcel inParcel, outParcel; 139 inParcel.writeInt32(op); 140 inParcel.writeInt32(refreshRate); 141 142 if(binder != NULL) { 143 err = binder->dispatch(IQService::CONFIGURE_DYN_REFRESH_RATE, 144 &inParcel, &outParcel); 145 } 146 147 if(err) 148 ALOGE("%s: Failed setting op %d err=%d", __FUNCTION__, op, err); 149 150 return err; 151 } 152 getConfigCount(int)153 int getConfigCount(int /*dpy*/) { 154 int numConfigs = -1; 155 sp<IQService> binder = getBinder(); 156 if(binder != NULL) { 157 Parcel inParcel, outParcel; 158 inParcel.writeInt32(DISPLAY_PRIMARY); 159 status_t err = binder->dispatch(IQService::GET_CONFIG_COUNT, 160 &inParcel, &outParcel); 161 if(!err) { 162 numConfigs = outParcel.readInt32(); 163 ALOGI("%s() Received num configs %d", __FUNCTION__, numConfigs); 164 } else { 165 ALOGE("%s() failed with err %d", __FUNCTION__, err); 166 } 167 } 168 return numConfigs; 169 } 170 getActiveConfig(int dpy)171 int getActiveConfig(int dpy) { 172 int configIndex = -1; 173 sp<IQService> binder = getBinder(); 174 if(binder != NULL) { 175 Parcel inParcel, outParcel; 176 inParcel.writeInt32(dpy); 177 status_t err = binder->dispatch(IQService::GET_ACTIVE_CONFIG, 178 &inParcel, &outParcel); 179 if(!err) { 180 configIndex = outParcel.readInt32(); 181 ALOGI("%s() Received active config index %d", __FUNCTION__, 182 configIndex); 183 } else { 184 ALOGE("%s() failed with err %d", __FUNCTION__, err); 185 } 186 } 187 return configIndex; 188 } 189 setActiveConfig(int configIndex,int)190 int setActiveConfig(int configIndex, int /*dpy*/) { 191 status_t err = (status_t) FAILED_TRANSACTION; 192 sp<IQService> binder = getBinder(); 193 if(binder != NULL) { 194 Parcel inParcel, outParcel; 195 inParcel.writeInt32(configIndex); 196 inParcel.writeInt32(DISPLAY_PRIMARY); 197 err = binder->dispatch(IQService::SET_ACTIVE_CONFIG, 198 &inParcel, &outParcel); 199 if(!err) { 200 ALOGI("%s() Successfully set active config index %d", __FUNCTION__, 201 configIndex); 202 } else { 203 ALOGE("%s() failed with err %d", __FUNCTION__, err); 204 } 205 } 206 return err; 207 } 208 getDisplayAttributes(int configIndex,int dpy)209 DisplayAttributes getDisplayAttributes(int configIndex, int dpy) { 210 DisplayAttributes dpyattr = {}; 211 sp<IQService> binder = getBinder(); 212 if(binder != NULL) { 213 Parcel inParcel, outParcel; 214 inParcel.writeInt32(configIndex); 215 inParcel.writeInt32(dpy); 216 status_t err = binder->dispatch( 217 IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG, &inParcel, 218 &outParcel); 219 if(!err) { 220 dpyattr.vsync_period = outParcel.readInt32(); 221 dpyattr.xres = outParcel.readInt32(); 222 dpyattr.yres = outParcel.readInt32(); 223 dpyattr.xdpi = outParcel.readFloat(); 224 dpyattr.ydpi = outParcel.readFloat(); 225 dpyattr.panel_type = outParcel.readInt32(); 226 dpyattr.is_yuv = outParcel.readInt32(); 227 ALOGI("%s() Received attrs for index %d: xres %d, yres %d", 228 __FUNCTION__, configIndex, dpyattr.xres, dpyattr.yres); 229 } else { 230 ALOGE("%s() failed with err %d", __FUNCTION__, err); 231 } 232 } 233 return dpyattr; 234 } 235 setPanelMode(int mode)236 int setPanelMode(int mode) { 237 status_t err = (status_t) FAILED_TRANSACTION; 238 sp<IQService> binder = getBinder(); 239 if(binder != NULL) { 240 Parcel inParcel, outParcel; 241 inParcel.writeInt32(mode); 242 err = binder->dispatch(IQService::SET_DISPLAY_MODE, 243 &inParcel, &outParcel); 244 if(!err) { 245 ALOGI("%s() Successfully set the display mode to %d", __FUNCTION__, 246 mode); 247 } else { 248 ALOGE("%s() failed with err %d", __FUNCTION__, err); 249 } 250 } 251 return err; 252 } 253 setPanelBrightness(int level)254 int setPanelBrightness(int level) { 255 status_t err = (status_t) FAILED_TRANSACTION; 256 sp<IQService> binder = getBinder(); 257 Parcel inParcel, outParcel; 258 259 if(binder != NULL) { 260 inParcel.writeInt32(level); 261 status_t err = binder->dispatch(IQService::SET_PANEL_BRIGHTNESS, 262 &inParcel, &outParcel); 263 if(err) { 264 ALOGE("%s() failed with err %d", __FUNCTION__, err); 265 } 266 } 267 return err; 268 } 269 getPanelBrightness()270 int getPanelBrightness() { 271 int panel_brightness = -1; 272 sp<IQService> binder = getBinder(); 273 Parcel inParcel, outParcel; 274 275 if(binder != NULL) { 276 status_t err = binder->dispatch(IQService::GET_PANEL_BRIGHTNESS, 277 &inParcel, &outParcel); 278 if(!err) { 279 panel_brightness = outParcel.readInt32(); 280 ALOGI("%s() Current panel brightness value %d", __FUNCTION__, 281 panel_brightness); 282 } else { 283 ALOGE("%s() failed with err %d", __FUNCTION__, err); 284 } 285 } 286 return panel_brightness; 287 } 288 setDsiClk(int dpy,uint64_t bitClk)289 int setDsiClk(int dpy, uint64_t bitClk) { 290 status_t err = (status_t) FAILED_TRANSACTION; 291 sp<IQService> binder = getBinder(); 292 Parcel inParcel, outParcel; 293 294 if(binder != NULL) { 295 inParcel.writeInt32(dpy); 296 inParcel.writeUint64(bitClk); 297 status_t err = binder->dispatch(IQService::SET_DSI_CLK, &inParcel, &outParcel); 298 if(err) { 299 ALOGE("%s() failed with err %d", __FUNCTION__, err); 300 } 301 } 302 return err; 303 } 304 getDsiClk(int dpy)305 uint64_t getDsiClk(int dpy) { 306 uint64_t dsi_clk = 0; 307 sp<IQService> binder = getBinder(); 308 Parcel inParcel, outParcel; 309 310 if(binder != NULL) { 311 inParcel.writeInt32(dpy); 312 status_t err = binder->dispatch(IQService::GET_DSI_CLK, &inParcel, &outParcel); 313 if(!err) { 314 dsi_clk = outParcel.readUint64(); 315 } else { 316 ALOGE("%s() failed with err %d", __FUNCTION__, err); 317 } 318 } 319 return dsi_clk; 320 } 321 getSupportedBitClk(int dpy,std::vector<uint64_t> & bit_rates)322 int getSupportedBitClk(int dpy, std::vector<uint64_t>& bit_rates) { 323 sp<IQService> binder = getBinder(); 324 Parcel inParcel, outParcel; 325 326 if(binder != NULL) { 327 inParcel.writeInt32(dpy); 328 status_t err = binder->dispatch(IQService::GET_SUPPORTED_DSI_CLK, &inParcel, &outParcel); 329 if(err) { 330 ALOGE("%s() failed with err %d", __FUNCTION__, err); 331 return err; 332 } 333 } 334 335 int32_t clk_levels = outParcel.readInt32(); 336 while (clk_levels > 0) { 337 bit_rates.push_back(outParcel.readUint64()); 338 clk_levels--; 339 } 340 return 0; 341 } 342 setPanelLuminanceAttributes(int dpy,float min_lum,float max_lum)343 int setPanelLuminanceAttributes(int dpy, float min_lum, float max_lum) { 344 status_t err = (status_t) FAILED_TRANSACTION; 345 sp<IQService> binder = getBinder(); 346 Parcel inParcel, outParcel; 347 348 if(binder != NULL) { 349 inParcel.writeInt32(dpy); 350 inParcel.writeFloat(min_lum); 351 inParcel.writeFloat(max_lum); 352 status_t err = binder->dispatch(IQService::SET_PANEL_LUMINANCE, &inParcel, &outParcel); 353 if(err) { 354 ALOGE("%s() failed with err %d", __FUNCTION__, err); 355 } 356 } 357 return err; 358 } 359 360 }// namespace 361 362 // ---------------------------------------------------------------------------- 363 // Functions for linking dynamically to libqdutils 364 // ---------------------------------------------------------------------------- minHdcpEncryptionLevelChanged(int dpy,int min_enc_level)365 extern "C" int minHdcpEncryptionLevelChanged(int dpy, int min_enc_level) { 366 status_t err = (status_t) FAILED_TRANSACTION; 367 sp<IQService> binder = getBinder(); 368 Parcel inParcel, outParcel; 369 inParcel.writeInt32(dpy); 370 inParcel.writeInt32(min_enc_level); 371 372 if(binder != NULL) { 373 err = binder->dispatch(IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED, 374 &inParcel, &outParcel); 375 } 376 377 if(err) { 378 ALOGE("%s: Failed for dpy %d err=%d", __FUNCTION__, dpy, err); 379 } else { 380 err = outParcel.readInt32(); 381 } 382 383 return err; 384 } 385 refreshScreen(int dpy)386 extern "C" int refreshScreen(int dpy) { 387 int ret = 0; 388 ret = screenRefresh(dpy); 389 return ret; 390 } 391 controlPartialUpdate(int dpy,int mode)392 extern "C" int controlPartialUpdate(int dpy, int mode) { 393 status_t err = (status_t) FAILED_TRANSACTION; 394 sp<IQService> binder = getBinder(); 395 if(binder != NULL) { 396 Parcel inParcel, outParcel; 397 inParcel.writeInt32(dpy); 398 inParcel.writeInt32(mode); 399 err = binder->dispatch(IQService::CONTROL_PARTIAL_UPDATE, &inParcel, &outParcel); 400 if(err != 0) { 401 ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err); 402 } else { 403 return outParcel.readInt32(); 404 } 405 } 406 407 return err; 408 } 409 410 // returns 0 if composer is up waitForComposerInit()411 extern "C" int waitForComposerInit() { 412 int status = false; 413 sp<IQService> binder = getBinder(); 414 if (binder == NULL) { 415 sleep(2); 416 binder = getBinder(); 417 } 418 419 if (binder != NULL) { 420 Parcel inParcel, outParcel; 421 binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel); 422 status = !!outParcel.readInt32(); 423 if (!status) { 424 sleep(2); 425 binder->dispatch(IQService::GET_COMPOSER_STATUS, &inParcel, &outParcel); 426 status = !!outParcel.readInt32(); 427 } 428 } 429 430 return !status; 431 } 432 setStandByMode(int mode,int is_twm=false)433 extern "C" int setStandByMode(int mode, int is_twm = false) { 434 status_t err = (status_t) FAILED_TRANSACTION; 435 sp<IQService> binder = getBinder(); 436 Parcel inParcel, outParcel; 437 438 if(binder != NULL) { 439 inParcel.writeInt32(mode); 440 inParcel.writeInt32(is_twm); 441 err = binder->dispatch(IQService::SET_STAND_BY_MODE, 442 &inParcel, &outParcel); 443 if(err) { 444 ALOGE("%s() failed with err %d", __FUNCTION__, err); 445 } 446 } 447 return err; 448 } 449 getPanelResolution(int * width,int * height)450 extern "C" int getPanelResolution(int *width, int *height) { 451 status_t err = (status_t) FAILED_TRANSACTION; 452 sp<IQService> binder = getBinder(); 453 Parcel inParcel, outParcel; 454 455 if(binder != NULL) { 456 err = binder->dispatch(IQService::GET_PANEL_RESOLUTION, 457 &inParcel, &outParcel); 458 if(err != 0) { 459 ALOGE_IF(getBinder(), "%s() failed with err %d", __FUNCTION__, err); 460 } else { 461 *width = outParcel.readInt32(); 462 *height = outParcel.readInt32(); 463 } 464 } 465 466 return err; 467 } 468 delayFirstCommit(void)469 extern "C" int delayFirstCommit(void) { 470 status_t err = (status_t) FAILED_TRANSACTION; 471 sp<IQService> binder = getBinder(); 472 if(binder != NULL) { 473 err = binder->dispatch(IQService::DELAY_FIRST_COMMIT, NULL, NULL); 474 if(err) { 475 ALOGE("%s() failed with err %d", __FUNCTION__, err); 476 } 477 } 478 return err; 479 } 480