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