1 /* 2 * Copyright (c) 2015 - 2017, 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 <dlfcn.h> 31 #include <cutils/sockets.h> 32 #include <cutils/native_handle.h> 33 #include <utils/String16.h> 34 #include <binder/Parcel.h> 35 #include <gralloc_priv.h> 36 #include <hardware/hwcomposer.h> 37 #include <hardware/hwcomposer_defs.h> 38 #include <QService.h> 39 40 #include <utils/constants.h> 41 #include <utils/debug.h> 42 #include <core/buffer_allocator.h> 43 #include <private/color_params.h> 44 #include "hwc_buffer_allocator.h" 45 #include "hwc_buffer_sync_handler.h" 46 #include "hwc_session.h" 47 #include "hwc_debugger.h" 48 49 #define __CLASS__ "HWCColorManager" 50 51 namespace sdm { 52 53 uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams ¶ms) { 54 uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) | 55 ((params.color.b) & 0xff); 56 return argb_color; 57 } 58 59 int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id, 60 PPDisplayAPIPayload *sink) { 61 int ret = 0; 62 uint32_t id(0); 63 uint32_t size(0); 64 65 id = UINT32(in.readInt32()); 66 size = UINT32(in.readInt32()); 67 if (size > 0 && size == in.dataAvail()) { 68 const void *data = in.readInplace(size); 69 const uint8_t *temp = reinterpret_cast<const uint8_t *>(data); 70 71 sink->size = size; 72 sink->payload = const_cast<uint8_t *>(temp); 73 *disp_id = id; 74 } else { 75 DLOGW("Failing size checking, size = %d", size); 76 ret = -EINVAL; 77 } 78 79 return ret; 80 } 81 82 void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data, 83 android::Parcel *out_parcel) { 84 out_parcel->writeInt32(INT32(data.size)); 85 if (data.payload) 86 out_parcel->write(data.payload, data.size); 87 } 88 89 HWCColorManager *HWCColorManager::CreateColorManager(HWCBufferAllocator * buffer_allocator) { 90 HWCColorManager *color_mgr = new HWCColorManager(buffer_allocator); 91 92 if (color_mgr) { 93 // Load display API interface library. And retrieve color API function tables. 94 DynLib &color_apis_lib = color_mgr->color_apis_lib_; 95 if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) { 96 if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) { 97 DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES, 98 DISPLAY_API_INTERFACE_LIBRARY_NAME); 99 delete color_mgr; 100 return NULL; 101 } 102 } else { 103 DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME); 104 delete color_mgr; 105 return NULL; 106 } 107 DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME); 108 109 // Load diagclient library and invokes its entry point to pass in display APIs. 110 DynLib &diag_client_lib = color_mgr->diag_client_lib_; 111 if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) { 112 if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME, 113 reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) || 114 !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME, 115 reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) { 116 DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME, 117 QDCM_DIAG_CLIENT_LIBRARY_NAME); 118 } else { 119 // invoke Diag Client entry point to initialize. 120 color_mgr->qdcm_diag_init_(color_mgr->color_apis_); 121 DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME, 122 QDCM_DIAG_CLIENT_LIBRARY_NAME); 123 } 124 } else { 125 DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME); 126 // only QDCM Diag client failed to be loaded and system still should function. 127 } 128 } else { 129 DLOGE("Unable to create HWCColorManager"); 130 return NULL; 131 } 132 133 return color_mgr; 134 } 135 136 HWCColorManager::HWCColorManager(HWCBufferAllocator *buffer_allocator) : 137 buffer_allocator_(buffer_allocator) { 138 } 139 140 HWCColorManager::~HWCColorManager() { 141 } 142 143 void HWCColorManager::DestroyColorManager() { 144 if (qdcm_mode_mgr_) { 145 delete qdcm_mode_mgr_; 146 } 147 if (qdcm_diag_deinit_) { 148 qdcm_diag_deinit_(); 149 } 150 delete this; 151 } 152 153 int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) { 154 int ret = 0; 155 156 if (!qdcm_mode_mgr_) { 157 qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr(); 158 if (!qdcm_mode_mgr_) { 159 DLOGE("Unable to create QDCM operating mode manager."); 160 ret = -EFAULT; 161 } 162 } 163 164 if (qdcm_mode_mgr_) { 165 ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display); 166 } 167 168 return ret; 169 } 170 171 int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) { 172 SCOPE_LOCK(locker_); 173 174 if (params) { 175 solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params); 176 } else { 177 solid_fill_params_ = PPColorFillParams(); 178 } 179 180 uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_); 181 if (enable) { 182 LayerRect solid_fill_rect = { 183 FLOAT(solid_fill_params_.rect.x), FLOAT(solid_fill_params_.rect.y), 184 FLOAT(solid_fill_params_.rect.x) + FLOAT(solid_fill_params_.rect.width), 185 FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height), 186 }; 187 188 hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color); 189 hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect); 190 } else { 191 hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0); 192 } 193 194 return 0; 195 } 196 197 int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) { 198 SCOPE_LOCK(locker_); 199 int ret = 0; 200 201 PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData *>(params); 202 203 if (enable) { 204 std::memset(&buffer_info, 0x00, sizeof(buffer_info)); 205 hwc_display->GetPanelResolution(&buffer_info.buffer_config.width, 206 &buffer_info.buffer_config.height); 207 if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) { 208 buffer_info.buffer_config.format = kFormatRGB888; 209 } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) { 210 buffer_info.buffer_config.format = kFormatRGBA1010102; 211 } else { 212 DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format); 213 return -EFAULT; 214 } 215 216 buffer_info.buffer_config.buffer_count = 1; 217 buffer_info.alloc_buffer_info.fd = -1; 218 buffer_info.alloc_buffer_info.stride = 0; 219 buffer_info.alloc_buffer_info.size = 0; 220 221 ret = buffer_allocator_->AllocateBuffer(&buffer_info); 222 if (ret != 0) { 223 DLOGE("Buffer allocation failed. ret: %d", ret); 224 return -ENOMEM; 225 } else { 226 void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size, PROT_READ | PROT_WRITE, 227 MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0); 228 229 if (buffer == MAP_FAILED) { 230 DLOGE("mmap failed. err = %d", errno); 231 frame_capture_data->buffer = NULL; 232 ret = buffer_allocator_->FreeBuffer(&buffer_info); 233 return -EFAULT; 234 } else { 235 frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer); 236 frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride; 237 frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size; 238 } 239 ret = hwc_display->FrameCaptureAsync(buffer_info, 1); 240 if (ret < 0) { 241 DLOGE("FrameCaptureAsync failed. ret = %d", ret); 242 } 243 } 244 } else { 245 ret = hwc_display->GetFrameCaptureStatus(); 246 if (!ret) { 247 if (frame_capture_data->buffer != NULL) { 248 if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) { 249 DLOGE("munmap failed. err = %d", errno); 250 } 251 } 252 if (buffer_allocator_ != NULL) { 253 std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData)); 254 ret = buffer_allocator_->FreeBuffer(&buffer_info); 255 if (ret != 0) { 256 DLOGE("FreeBuffer failed. ret = %d", ret); 257 } 258 } 259 } else { 260 DLOGE("GetFrameCaptureStatus failed. ret = %d", ret); 261 } 262 } 263 return ret; 264 } 265 266 int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) { 267 int err = -1; 268 DisplayDetailEnhancerData de_data; 269 270 PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params); 271 if (de_tuning_cfg_data->cfg_pending == true) { 272 if (!de_tuning_cfg_data->cfg_en) { 273 de_data.enable = 0; 274 } else { 275 de_data.override_flags = kOverrideDEEnable; 276 de_data.enable = 1; 277 278 if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) { 279 de_data.override_flags |= kOverrideDESharpen1; 280 de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor; 281 } 282 283 if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) { 284 de_data.override_flags |= kOverrideDEClip; 285 de_data.clip = de_tuning_cfg_data->params.clip; 286 } 287 288 if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) { 289 de_data.override_flags |= kOverrideDEThrQuiet; 290 de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet; 291 } 292 293 if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) { 294 de_data.override_flags |= kOverrideDEThrDieout; 295 de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout; 296 } 297 298 if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) { 299 de_data.override_flags |= kOverrideDEThrLow; 300 de_data.thr_low = de_tuning_cfg_data->params.thr_low; 301 } 302 303 if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) { 304 de_data.override_flags |= kOverrideDEThrHigh; 305 de_data.thr_high = de_tuning_cfg_data->params.thr_high; 306 } 307 308 if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) { 309 switch (de_tuning_cfg_data->params.quality) { 310 case kDeContentQualLow: 311 de_data.quality_level = kContentQualityLow; 312 break; 313 case kDeContentQualMedium: 314 de_data.quality_level = kContentQualityMedium; 315 break; 316 case kDeContentQualHigh: 317 de_data.quality_level = kContentQualityHigh; 318 break; 319 case kDeContentQualUnknown: 320 default: 321 de_data.quality_level = kContentQualityUnknown; 322 break; 323 } 324 } 325 } 326 err = hwc_display->SetDetailEnhancerConfig(de_data); 327 if (err) { 328 DLOGW("SetDetailEnhancerConfig failed. err = %d", err); 329 } 330 de_tuning_cfg_data->cfg_pending = false; 331 } 332 return err; 333 } 334 335 void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) { 336 SCOPE_LOCK(locker_); 337 int err = -1; 338 PPPendingParams pending_action; 339 PPDisplayAPIPayload req_payload; 340 341 pending_action.action = kGetDetailedEnhancerData; 342 pending_action.params = NULL; 343 344 if (hwc_display) { 345 err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action); 346 if (!err && pending_action.action == kConfigureDetailedEnhancer) { 347 err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display); 348 } 349 } 350 return; 351 } 352 353 int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) { 354 SCOPE_LOCK(locker_); 355 int err = -1; 356 err = SetHWDetailedEnhancerConfig(params, hwc_display); 357 return err; 358 } 359 360 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = { 361 HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"), 362 HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"), 363 HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"), 364 }; 365 366 const char *const HWCQDCMModeManager::kSocketName = "pps"; 367 const char *const HWCQDCMModeManager::kTagName = "surfaceflinger"; 368 const char *const HWCQDCMModeManager::kPackageName = "colormanager"; 369 370 HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() { 371 HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager(); 372 373 if (!mode_mgr) { 374 DLOGW("No memory to create HWCQDCMModeManager."); 375 return NULL; 376 } else { 377 mode_mgr->socket_fd_ = 378 ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); 379 if (mode_mgr->socket_fd_ < 0) { 380 // it should not be disastrous and we still can grab wakelock in QDCM mode. 381 DLOGW("Unable to connect to dpps socket!"); 382 } 383 384 // retrieve system GPU idle timeout value for later to recover. 385 mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs()); 386 } 387 388 return mode_mgr; 389 } 390 391 HWCQDCMModeManager::~HWCQDCMModeManager() { 392 if (socket_fd_ >= 0) 393 ::close(socket_fd_); 394 } 395 396 int HWCQDCMModeManager::EnableActiveFeatures(bool enable, 397 const HWCQDCMModeManager::ActiveFeatureCMD &cmds, 398 bool *was_running) { 399 int ret = 0; 400 ssize_t size = 0; 401 char response[kSocketCMDMaxLength] = { 402 0, 403 }; 404 405 if (socket_fd_ < 0) { 406 DLOGW("No socket connection available!"); 407 return -EFAULT; 408 } 409 410 if (!enable) { // if client requesting to disable it. 411 // query CABL status, if off, no action. keep the status. 412 size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status)); 413 if (size < 0) { 414 DLOGW("Unable to send data over socket %s", ::strerror(errno)); 415 ret = -EFAULT; 416 } else { 417 size = ::read(socket_fd_, response, kSocketCMDMaxLength); 418 if (size < 0) { 419 DLOGW("Unable to read data over socket %s", ::strerror(errno)); 420 ret = -EFAULT; 421 } else if (!strncmp(response, cmds.running, strlen(cmds.running))) { 422 *was_running = true; 423 } 424 } 425 426 if (*was_running) { // if was running, it's requested to disable it. 427 size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off)); 428 if (size < 0) { 429 DLOGW("Unable to send data over socket %s", ::strerror(errno)); 430 ret = -EFAULT; 431 } 432 } 433 } else { // if was running, need enable it back. 434 if (*was_running) { 435 size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on)); 436 if (size < 0) { 437 DLOGW("Unable to send data over socket %s", ::strerror(errno)); 438 ret = -EFAULT; 439 } 440 } 441 } 442 443 return ret; 444 } 445 446 int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) { 447 int ret = 0; 448 449 ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature], 450 &cabl_was_running_); 451 452 // if enter QDCM mode, disable GPU fallback idle timeout. 453 if (hwc_display) { 454 uint32_t timeout = enable ? 0 : entry_timeout_; 455 hwc_display->SetIdleTimeoutMs(timeout); 456 } 457 458 return ret; 459 } 460 461 } // namespace sdm 462