Home | History | Annotate | Download | only in hwc
      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 <powermanager/IPowerManager.h>
     32 #include <cutils/sockets.h>
     33 #include <cutils/native_handle.h>
     34 #include <utils/String16.h>
     35 #include <binder/Parcel.h>
     36 #include <gralloc_priv.h>
     37 #include <hardware/hwcomposer.h>
     38 #include <hardware/hwcomposer_defs.h>
     39 #include <QService.h>
     40 
     41 #include <core/dump_interface.h>
     42 #include <utils/constants.h>
     43 #include <utils/debug.h>
     44 #include <core/buffer_allocator.h>
     45 #include <private/color_params.h>
     46 #include "hwc_buffer_allocator.h"
     47 #include "hwc_buffer_sync_handler.h"
     48 #include "hwc_session.h"
     49 #include "hwc_debugger.h"
     50 
     51 #define __CLASS__ "HWCColorManager"
     52 
     53 namespace sdm {
     54 
     55 uint32_t HWCColorManager::Get8BitsARGBColorValue(const PPColorFillParams &params) {
     56   uint32_t argb_color = ((params.color.r << 16) & 0xff0000) | ((params.color.g << 8) & 0xff00) |
     57                         ((params.color.b) & 0xff);
     58   return argb_color;
     59 }
     60 
     61 int HWCColorManager::CreatePayloadFromParcel(const android::Parcel &in, uint32_t *disp_id,
     62                                              PPDisplayAPIPayload *sink) {
     63   int ret = 0;
     64   uint32_t id(0);
     65   uint32_t size(0);
     66 
     67   id = UINT32(in.readInt32());
     68   size = UINT32(in.readInt32());
     69   if (size > 0 && size == in.dataAvail()) {
     70     const void *data = in.readInplace(size);
     71     const uint8_t *temp = reinterpret_cast<const uint8_t *>(data);
     72 
     73     sink->size = size;
     74     sink->payload = const_cast<uint8_t *>(temp);
     75     *disp_id = id;
     76   } else {
     77     DLOGW("Failing size checking, size = %d", size);
     78     ret = -EINVAL;
     79   }
     80 
     81   return ret;
     82 }
     83 
     84 void HWCColorManager::MarshallStructIntoParcel(const PPDisplayAPIPayload &data,
     85                                                android::Parcel *out_parcel) {
     86   out_parcel->writeInt32(INT32(data.size));
     87   if (data.payload)
     88     out_parcel->write(data.payload, data.size);
     89 }
     90 
     91 HWCColorManager *HWCColorManager::CreateColorManager() {
     92   HWCColorManager *color_mgr = new HWCColorManager();
     93 
     94   if (color_mgr) {
     95     // Load display API interface library. And retrieve color API function tables.
     96     DynLib &color_apis_lib = color_mgr->color_apis_lib_;
     97     if (color_apis_lib.Open(DISPLAY_API_INTERFACE_LIBRARY_NAME)) {
     98       if (!color_apis_lib.Sym(DISPLAY_API_FUNC_TABLES, &color_mgr->color_apis_)) {
     99         DLOGE("Fail to retrieve = %s from %s", DISPLAY_API_FUNC_TABLES,
    100               DISPLAY_API_INTERFACE_LIBRARY_NAME);
    101         delete color_mgr;
    102         return NULL;
    103       }
    104     } else {
    105       DLOGW("Unable to load = %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
    106       delete color_mgr;
    107       return NULL;
    108     }
    109     DLOGI("Successfully loaded %s", DISPLAY_API_INTERFACE_LIBRARY_NAME);
    110 
    111     // Load diagclient library and invokes its entry point to pass in display APIs.
    112     DynLib &diag_client_lib = color_mgr->diag_client_lib_;
    113     if (diag_client_lib.Open(QDCM_DIAG_CLIENT_LIBRARY_NAME)) {
    114       if (!diag_client_lib.Sym(INIT_QDCM_DIAG_CLIENT_NAME,
    115                                reinterpret_cast<void **>(&color_mgr->qdcm_diag_init_)) ||
    116         !diag_client_lib.Sym(DEINIT_QDCM_DIAG_CLIENT_NAME,
    117                                reinterpret_cast<void **>(&color_mgr->qdcm_diag_deinit_))) {
    118         DLOGE("Fail to retrieve = %s from %s", INIT_QDCM_DIAG_CLIENT_NAME,
    119               QDCM_DIAG_CLIENT_LIBRARY_NAME);
    120       } else {
    121         // invoke Diag Client entry point to initialize.
    122         color_mgr->qdcm_diag_init_(color_mgr->color_apis_);
    123         DLOGI("Successfully loaded %s and %s and diag_init'ed", DISPLAY_API_INTERFACE_LIBRARY_NAME,
    124               QDCM_DIAG_CLIENT_LIBRARY_NAME);
    125       }
    126     } else {
    127       DLOGW("Unable to load = %s", QDCM_DIAG_CLIENT_LIBRARY_NAME);
    128       // only QDCM Diag client failed to be loaded and system still should function.
    129     }
    130   } else {
    131     DLOGE("Unable to create HWCColorManager");
    132     return NULL;
    133   }
    134 
    135   return color_mgr;
    136 }
    137 
    138 HWCColorManager::~HWCColorManager() {
    139 }
    140 
    141 void HWCColorManager::DestroyColorManager() {
    142   if (qdcm_mode_mgr_) {
    143     delete qdcm_mode_mgr_;
    144   }
    145   if (qdcm_diag_deinit_) {
    146     qdcm_diag_deinit_();
    147   }
    148   delete this;
    149 }
    150 
    151 int HWCColorManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
    152   int ret = 0;
    153 
    154   if (!qdcm_mode_mgr_) {
    155     qdcm_mode_mgr_ = HWCQDCMModeManager::CreateQDCMModeMgr();
    156     if (!qdcm_mode_mgr_) {
    157       DLOGE("Unable to create QDCM operating mode manager.");
    158       ret = -EFAULT;
    159     }
    160   }
    161 
    162   if (qdcm_mode_mgr_) {
    163     ret = qdcm_mode_mgr_->EnableQDCMMode(enable, hwc_display);
    164   }
    165 
    166   return ret;
    167 }
    168 
    169 bool HWCColorManager::SolidFillLayersPrepare(hwc_display_contents_1_t **displays,
    170                                              HWCDisplay *hwc_display) {
    171   SCOPE_LOCK(locker_);
    172 
    173   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
    174   uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
    175   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
    176 
    177   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
    178     // 1. shallow copy HWC_FRAMEBUFFER_TARGET layer info solid fill layer list.
    179     solid_fill_layers_->hwLayers[1] = layer_list->hwLayers[layer_list->numHwLayers - 1];
    180 
    181     // 2. continue the prepare<> on solid_fill_layers.
    182     hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
    183     hwc_display->Prepare(solid_fill_layers_);  // RECT info included.
    184 
    185     // 3. Set HWC_OVERLAY to all SF layers before returning to framework.
    186     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
    187       hwc_layer_1_t *layer = &layer_list->hwLayers[i];
    188       layer->compositionType = HWC_OVERLAY;
    189     }
    190 
    191     return true;
    192   } else if (!solid_fill_enable_) {
    193     hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
    194   }
    195 
    196   return false;
    197 }
    198 
    199 bool HWCColorManager::SolidFillLayersSet(hwc_display_contents_1_t **displays,
    200                                          HWCDisplay *hwc_display) {
    201   // Query HWCColorManager if QDCM tool requesting SOLID_FILL mode.
    202   SCOPE_LOCK(locker_);
    203   hwc_display_contents_1_t *layer_list = displays[HWC_DISPLAY_PRIMARY];
    204   if (solid_fill_enable_ && solid_fill_layers_ && layer_list) {
    205     hwc_display->Commit(solid_fill_layers_);
    206 
    207     // SurfaceFlinger layer stack is dropped in solid fill case and replaced with local layer stack
    208     // Close acquire fence fds associated with SF layer stack
    209     // Close release/retire fence fds returned along with local layer stack
    210     for (size_t i = 0; i < (layer_list->numHwLayers - 1); i++) {
    211       int &fence_fd = layer_list->hwLayers[i].acquireFenceFd;
    212       if (fence_fd >= 0) {
    213         close(fence_fd);
    214         fence_fd = -1;
    215       }
    216     }
    217 
    218     for (size_t i = 0; i < (solid_fill_layers_->numHwLayers - 1); i++) {
    219       int &fence_fd = solid_fill_layers_->hwLayers[i].releaseFenceFd;
    220       if (fence_fd >= 0) {
    221         close(fence_fd);
    222         fence_fd = -1;
    223       }
    224     }
    225     if (solid_fill_layers_->retireFenceFd >= 0) {
    226       close(solid_fill_layers_->retireFenceFd);
    227       solid_fill_layers_->retireFenceFd = -1;
    228     }
    229 
    230     return true;
    231   }
    232 
    233   return false;
    234 }
    235 
    236 int HWCColorManager::CreateSolidFillLayers(HWCDisplay *hwc_display) {
    237   int ret = 0;
    238 
    239   if (!solid_fill_layers_) {
    240     uint32_t size = sizeof(hwc_display_contents_1) + kNumSolidFillLayers * sizeof(hwc_layer_1_t);
    241     uint32_t primary_width = 0;
    242     uint32_t primary_height = 0;
    243 
    244     hwc_display->GetMixerResolution(&primary_width, &primary_height);
    245     uint8_t *buf = new uint8_t[size]();
    246     // handle for solid fill layer with fd = -1.
    247     private_handle_t *handle =
    248         new private_handle_t(-1, 0, private_handle_t::PRIV_FLAGS_FRAMEBUFFER, BUFFER_TYPE_UI,
    249                              HAL_PIXEL_FORMAT_RGBA_8888, INT32(primary_width),
    250                              INT32(primary_height));
    251 
    252     if (!buf || !handle) {
    253       DLOGE("Failed to allocate memory.");
    254       if (buf)
    255         delete[] buf;
    256       if (handle)
    257         delete handle;
    258 
    259       return -ENOMEM;
    260     }
    261 
    262     solid_fill_layers_ = reinterpret_cast<hwc_display_contents_1 *>(buf);
    263     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
    264     layer.handle = handle;
    265   }
    266 
    267   solid_fill_layers_->flags = HWC_GEOMETRY_CHANGED;
    268   solid_fill_layers_->numHwLayers = kNumSolidFillLayers;
    269   solid_fill_layers_->retireFenceFd = -1;
    270   solid_fill_layers_->outbuf = NULL;
    271   solid_fill_layers_->outbufAcquireFenceFd = -1;
    272 
    273   hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
    274   hwc_rect_t solid_fill_rect = {
    275       INT(solid_fill_params_.rect.x),
    276       INT(solid_fill_params_.rect.y),
    277       solid_fill_params_.rect.x + INT(solid_fill_params_.rect.width),
    278       solid_fill_params_.rect.y + INT(solid_fill_params_.rect.height),
    279   };
    280 
    281   layer.compositionType = HWC_FRAMEBUFFER;
    282   layer.blending = HWC_BLENDING_PREMULT;
    283   layer.sourceCropf.left = solid_fill_params_.rect.x;
    284   layer.sourceCropf.top = solid_fill_params_.rect.y;
    285   layer.sourceCropf.right = UINT32(solid_fill_params_.rect.x) + solid_fill_params_.rect.width;
    286   layer.sourceCropf.bottom = UINT32(solid_fill_params_.rect.y) + solid_fill_params_.rect.height;
    287   layer.acquireFenceFd = -1;
    288   layer.releaseFenceFd = -1;
    289   layer.flags = 0;
    290   layer.transform = 0;
    291   layer.hints = 0;
    292   layer.planeAlpha = 0xff;
    293   layer.displayFrame = solid_fill_rect;
    294   layer.visibleRegionScreen.numRects = 1;
    295   layer.visibleRegionScreen.rects = &layer.displayFrame;
    296   layer.surfaceDamage.numRects = 0;
    297 
    298   return ret;
    299 }
    300 
    301 void HWCColorManager::DestroySolidFillLayers() {
    302   if (solid_fill_layers_) {
    303     hwc_layer_1_t &layer = solid_fill_layers_->hwLayers[0];
    304     uint8_t *buf = reinterpret_cast<uint8_t *>(solid_fill_layers_);
    305     private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(layer.handle);
    306 
    307     if (hnd)
    308         delete hnd;
    309 
    310     if (buf)
    311         delete[] buf;
    312 
    313     solid_fill_layers_ = NULL;
    314   }
    315 }
    316 
    317 int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
    318   SCOPE_LOCK(locker_);
    319   int ret = 0;
    320 
    321   if (params) {
    322     solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
    323   } else {
    324     solid_fill_params_ = PPColorFillParams();
    325   }
    326 
    327   if (enable) {
    328     // will create solid fill layers for rendering if not present.
    329     ret = CreateSolidFillLayers(hwc_display);
    330   } else {
    331     DestroySolidFillLayers();
    332   }
    333   solid_fill_enable_ = enable;
    334 
    335   return ret;
    336 }
    337 
    338 int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
    339   SCOPE_LOCK(locker_);
    340   int ret = 0;
    341 
    342   PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData*>(params);
    343 
    344   if (enable) {
    345     std::memset(&buffer_info, 0x00, sizeof(buffer_info));
    346     hwc_display->GetPanelResolution(&buffer_info.buffer_config.width,
    347                                     &buffer_info.buffer_config.height);
    348     if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
    349       buffer_info.buffer_config.format = kFormatRGB888;
    350     } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
    351       buffer_info.buffer_config.format = kFormatRGBA1010102;
    352     } else {
    353       DLOGE("Pixel-format: %d NOT support.", frame_capture_data->input_params.out_pix_format);
    354       return -EFAULT;
    355     }
    356 
    357     buffer_info.buffer_config.buffer_count = 1;
    358     buffer_info.alloc_buffer_info.fd = -1;
    359     buffer_info.alloc_buffer_info.stride = 0;
    360     buffer_info.alloc_buffer_info.size = 0;
    361 
    362     buffer_allocator_ = new HWCBufferAllocator();
    363     if (buffer_allocator_ == NULL) {
    364       DLOGE("Memory allocation for buffer_allocator_ FAILED");
    365       return -ENOMEM;
    366     }
    367 
    368     ret = buffer_allocator_->AllocateBuffer(&buffer_info);
    369     if (ret != 0) {
    370       DLOGE("Buffer allocation failed. ret: %d", ret);
    371       delete buffer_allocator_;
    372       buffer_allocator_ = NULL;
    373       return -ENOMEM;
    374     } else {
    375       void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size,
    376                           PROT_READ|PROT_WRITE,
    377                           MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
    378 
    379       if (buffer == MAP_FAILED) {
    380         DLOGE("mmap failed. err = %d", errno);
    381         frame_capture_data->buffer = NULL;
    382         ret = buffer_allocator_->FreeBuffer(&buffer_info);
    383         delete buffer_allocator_;
    384         buffer_allocator_ = NULL;
    385         return -EFAULT;
    386       } else {
    387         frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
    388         frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.aligned_width;
    389         frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
    390       }
    391       ret = hwc_display->FrameCaptureAsync(buffer_info, 1);
    392       if (ret < 0) {
    393         DLOGE("FrameCaptureAsync failed. ret = %d", ret);
    394       }
    395     }
    396   } else {
    397     ret = hwc_display->GetFrameCaptureStatus();
    398     if (!ret) {
    399       if (frame_capture_data->buffer != NULL) {
    400         if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
    401           DLOGE("munmap failed. err = %d", errno);
    402         }
    403       }
    404       if (buffer_allocator_ != NULL) {
    405         std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
    406         ret = buffer_allocator_->FreeBuffer(&buffer_info);
    407         if (ret != 0) {
    408           DLOGE("FreeBuffer failed. ret = %d", ret);
    409         }
    410         delete buffer_allocator_;
    411         buffer_allocator_ = NULL;
    412       }
    413     } else {
    414       DLOGE("GetFrameCaptureStatus failed. ret = %d", ret);
    415     }
    416   }
    417   return ret;
    418 }
    419 
    420 int HWCColorManager::SetHWDetailedEnhancerConfig(void *params, HWCDisplay *hwc_display) {
    421   int err = -1;
    422   DisplayDetailEnhancerData de_data;
    423 
    424   PPDETuningCfgData *de_tuning_cfg_data = reinterpret_cast<PPDETuningCfgData*>(params);
    425   if (de_tuning_cfg_data->cfg_pending == true) {
    426     if (!de_tuning_cfg_data->cfg_en) {
    427       de_data.enable = 0;
    428     } else {
    429       de_data.override_flags = kOverrideDEEnable;
    430       de_data.enable = 1;
    431 
    432       if (de_tuning_cfg_data->params.flags & kDeTuningFlagSharpFactor) {
    433         de_data.override_flags |= kOverrideDESharpen1;
    434         de_data.sharp_factor = de_tuning_cfg_data->params.sharp_factor;
    435       }
    436 
    437       if (de_tuning_cfg_data->params.flags & kDeTuningFlagClip) {
    438         de_data.override_flags |= kOverrideDEClip;
    439         de_data.clip = de_tuning_cfg_data->params.clip;
    440       }
    441 
    442       if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrQuiet) {
    443         de_data.override_flags |= kOverrideDEThrQuiet;
    444         de_data.thr_quiet = de_tuning_cfg_data->params.thr_quiet;
    445       }
    446 
    447       if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrDieout) {
    448         de_data.override_flags |= kOverrideDEThrDieout;
    449         de_data.thr_dieout = de_tuning_cfg_data->params.thr_dieout;
    450       }
    451 
    452       if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrLow) {
    453         de_data.override_flags |= kOverrideDEThrLow;
    454         de_data.thr_low = de_tuning_cfg_data->params.thr_low;
    455       }
    456 
    457       if (de_tuning_cfg_data->params.flags & kDeTuningFlagThrHigh) {
    458         de_data.override_flags |= kOverrideDEThrHigh;
    459         de_data.thr_high = de_tuning_cfg_data->params.thr_high;
    460       }
    461 
    462       if (de_tuning_cfg_data->params.flags & kDeTuningFlagContentQualLevel) {
    463         switch (de_tuning_cfg_data->params.quality) {
    464           case kDeContentQualLow:
    465             de_data.quality_level = kContentQualityLow;
    466             break;
    467           case kDeContentQualMedium:
    468             de_data.quality_level = kContentQualityMedium;
    469             break;
    470           case kDeContentQualHigh:
    471             de_data.quality_level = kContentQualityHigh;
    472             break;
    473           case kDeContentQualUnknown:
    474           default:
    475             de_data.quality_level = kContentQualityUnknown;
    476             break;
    477         }
    478       }
    479     }
    480     err = hwc_display->SetDetailEnhancerConfig(de_data);
    481     if (err) {
    482       DLOGW("SetDetailEnhancerConfig failed. err = %d", err);
    483     }
    484     de_tuning_cfg_data->cfg_pending = false;
    485   }
    486   return err;
    487 }
    488 
    489 void HWCColorManager::SetColorModeDetailEnhancer(HWCDisplay *hwc_display) {
    490   SCOPE_LOCK(locker_);
    491   int err = -1;
    492   PPPendingParams pending_action;
    493   PPDisplayAPIPayload req_payload;
    494 
    495   pending_action.action = kGetDetailedEnhancerData;
    496   pending_action.params = NULL;
    497 
    498   if (hwc_display) {
    499     err = hwc_display->ColorSVCRequestRoute(req_payload, NULL, &pending_action);
    500     if (!err && pending_action.action == kConfigureDetailedEnhancer) {
    501       err = SetHWDetailedEnhancerConfig(pending_action.params, hwc_display);
    502     }
    503   }
    504   return;
    505 }
    506 
    507 int HWCColorManager::SetDetailedEnhancer(void *params, HWCDisplay *hwc_display) {
    508   SCOPE_LOCK(locker_);
    509   int err = -1;
    510   err = SetHWDetailedEnhancerConfig(params, hwc_display);
    511   return err;
    512 }
    513 
    514 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
    515     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
    516     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
    517     HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
    518 };
    519 
    520 const char *const HWCQDCMModeManager::kSocketName = "pps";
    521 const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
    522 const char *const HWCQDCMModeManager::kPackageName = "colormanager";
    523 
    524 HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
    525   HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
    526 
    527   if (!mode_mgr) {
    528     DLOGW("No memory to create HWCQDCMModeManager.");
    529     return NULL;
    530   } else {
    531     mode_mgr->socket_fd_ =
    532         ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    533     if (mode_mgr->socket_fd_ < 0) {
    534       // it should not be disastrous and we still can grab wakelock in QDCM mode.
    535       DLOGW("Unable to connect to dpps socket!");
    536     }
    537 
    538     // retrieve system GPU idle timeout value for later to recover.
    539     mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
    540 
    541     // acquire the binder handle to Android system PowerManager for later use.
    542     android::sp<android::IBinder> binder =
    543         android::defaultServiceManager()->checkService(android::String16("power"));
    544     if (binder == NULL) {
    545       DLOGW("Application can't connect to  power manager service");
    546       delete mode_mgr;
    547       mode_mgr = NULL;
    548     } else {
    549       mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
    550     }
    551   }
    552 
    553   return mode_mgr;
    554 }
    555 
    556 HWCQDCMModeManager::~HWCQDCMModeManager() {
    557   if (socket_fd_ >= 0)
    558     ::close(socket_fd_);
    559 }
    560 
    561 int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
    562   int ret = 0;
    563 
    564   if (enable) {
    565     if (wakelock_token_ == NULL) {
    566       android::sp<android::IBinder> binder = new android::BBinder();
    567       android::status_t status = power_mgr_->acquireWakeLock(
    568           (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
    569           android::String16(kTagName), android::String16(kPackageName));
    570       if (status == android::NO_ERROR) {
    571         wakelock_token_ = binder;
    572       }
    573     }
    574   } else {
    575     if (wakelock_token_ != NULL && power_mgr_ != NULL) {
    576       power_mgr_->releaseWakeLock(wakelock_token_, 0);
    577       wakelock_token_.clear();
    578       wakelock_token_ = NULL;
    579     }
    580   }
    581 
    582   return ret;
    583 }
    584 
    585 int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
    586                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
    587                                              bool *was_running) {
    588   int ret = 0;
    589   ssize_t size = 0;
    590   char response[kSocketCMDMaxLength] = {
    591       0,
    592   };
    593 
    594   if (socket_fd_ < 0) {
    595     DLOGW("No socket connection available!");
    596     return -EFAULT;
    597   }
    598 
    599   if (!enable) {  // if client requesting to disable it.
    600     // query CABL status, if off, no action. keep the status.
    601     size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
    602     if (size < 0) {
    603       DLOGW("Unable to send data over socket %s", ::strerror(errno));
    604       ret = -EFAULT;
    605     } else {
    606       size = ::read(socket_fd_, response, kSocketCMDMaxLength);
    607       if (size < 0) {
    608         DLOGW("Unable to read data over socket %s", ::strerror(errno));
    609         ret = -EFAULT;
    610       } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
    611         *was_running = true;
    612       }
    613     }
    614 
    615     if (*was_running) {  // if was running, it's requested to disable it.
    616       size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
    617       if (size < 0) {
    618         DLOGW("Unable to send data over socket %s", ::strerror(errno));
    619         ret = -EFAULT;
    620       }
    621     }
    622   } else {  // if was running, need enable it back.
    623     if (*was_running) {
    624       size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
    625       if (size < 0) {
    626         DLOGW("Unable to send data over socket %s", ::strerror(errno));
    627         ret = -EFAULT;
    628       }
    629     }
    630   }
    631 
    632   return ret;
    633 }
    634 
    635 int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
    636   int ret = 0;
    637 
    638   ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
    639                              &cabl_was_running_);
    640   ret = AcquireAndroidWakeLock(enable);
    641 
    642   // if enter QDCM mode, disable GPU fallback idle timeout.
    643   if (hwc_display) {
    644     uint32_t timeout = enable ? 0 : entry_timeout_;
    645     hwc_display->SetIdleTimeoutMs(timeout);
    646   }
    647 
    648   return ret;
    649 }
    650 
    651 }  // namespace sdm
    652