Home | History | Annotate | Download | only in hwc2
      1 /*
      2 * Copyright (c) 2015 - 2016, 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 int HWCColorManager::SetSolidFill(const void *params, bool enable, HWCDisplay *hwc_display) {
    170   SCOPE_LOCK(locker_);
    171 
    172   if (params) {
    173     solid_fill_params_ = *reinterpret_cast<const PPColorFillParams *>(params);
    174   } else {
    175     solid_fill_params_ = PPColorFillParams();
    176   }
    177 
    178   uint32_t solid_fill_color = Get8BitsARGBColorValue(solid_fill_params_);
    179   if (enable) {
    180     LayerRect solid_fill_rect = {
    181       FLOAT(solid_fill_params_.rect.x), FLOAT(solid_fill_params_.rect.y),
    182       FLOAT(solid_fill_params_.rect.x) + FLOAT(solid_fill_params_.rect.width),
    183       FLOAT(solid_fill_params_.rect.y) + FLOAT(solid_fill_params_.rect.height),
    184     };
    185 
    186     hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_INFO, solid_fill_color);
    187     hwc_display->Perform(HWCDisplayPrimary::SET_QDCM_SOLID_FILL_RECT, &solid_fill_rect);
    188   } else {
    189     hwc_display->Perform(HWCDisplayPrimary::UNSET_QDCM_SOLID_FILL_INFO, 0);
    190   }
    191 
    192   return 0;
    193 }
    194 
    195 int HWCColorManager::SetFrameCapture(void *params, bool enable, HWCDisplay *hwc_display) {
    196   SCOPE_LOCK(locker_);
    197   int ret = 0;
    198 
    199   PPFrameCaptureData *frame_capture_data = reinterpret_cast<PPFrameCaptureData *>(params);
    200 
    201   if (enable) {
    202     std::memset(&buffer_info, 0x00, sizeof(buffer_info));
    203     hwc_display->GetFrameBufferResolution(&buffer_info.buffer_config.width,
    204                                           &buffer_info.buffer_config.height);
    205     if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_888) {
    206       buffer_info.buffer_config.format = kFormatRGB888;
    207     } else if (frame_capture_data->input_params.out_pix_format == PP_PIXEL_FORMAT_RGB_2101010) {
    208       // TODO(user): Complete the implementation
    209       DLOGE("RGB 10-bit format NOT supported");
    210       return -EFAULT;
    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     buffer_allocator_ = new HWCBufferAllocator();
    222     if (buffer_allocator_ == NULL) {
    223       DLOGE("Memory allocation for buffer_allocator_ FAILED");
    224       return -ENOMEM;
    225     }
    226 
    227     ret = buffer_allocator_->AllocateBuffer(&buffer_info);
    228     if (ret != 0) {
    229       DLOGE("Buffer allocation failed. ret: %d", ret);
    230       delete[] buffer_allocator_;
    231       buffer_allocator_ = NULL;
    232       return -ENOMEM;
    233     } else {
    234       void *buffer = mmap(NULL, buffer_info.alloc_buffer_info.size, PROT_READ | PROT_WRITE,
    235                           MAP_SHARED, buffer_info.alloc_buffer_info.fd, 0);
    236 
    237       if (buffer == MAP_FAILED) {
    238         DLOGE("mmap failed. err = %d", errno);
    239         frame_capture_data->buffer = NULL;
    240         ret = buffer_allocator_->FreeBuffer(&buffer_info);
    241         delete[] buffer_allocator_;
    242         buffer_allocator_ = NULL;
    243         return -EFAULT;
    244       } else {
    245         frame_capture_data->buffer = reinterpret_cast<uint8_t *>(buffer);
    246         frame_capture_data->buffer_stride = buffer_info.alloc_buffer_info.stride;
    247         frame_capture_data->buffer_size = buffer_info.alloc_buffer_info.size;
    248       }
    249       // TODO(user): Call HWC interface to provide the buffer and rectangle information
    250     }
    251   } else {
    252     if (frame_capture_data->buffer != NULL) {
    253       if (munmap(frame_capture_data->buffer, buffer_info.alloc_buffer_info.size) != 0) {
    254         DLOGE("munmap failed. err = %d", errno);
    255       }
    256     }
    257     if (buffer_allocator_ != NULL) {
    258       std::memset(frame_capture_data, 0x00, sizeof(PPFrameCaptureData));
    259       ret = buffer_allocator_->FreeBuffer(&buffer_info);
    260       if (ret != 0) {
    261         DLOGE("FreeBuffer failed. ret = %d", ret);
    262       }
    263       delete[] buffer_allocator_;
    264       buffer_allocator_ = NULL;
    265     }
    266   }
    267   return ret;
    268 }
    269 
    270 const HWCQDCMModeManager::ActiveFeatureCMD HWCQDCMModeManager::kActiveFeatureCMD[] = {
    271     HWCQDCMModeManager::ActiveFeatureCMD("cabl:on", "cabl:off", "cabl:status", "running"),
    272     HWCQDCMModeManager::ActiveFeatureCMD("ad:on", "ad:off", "ad:query:status", "running"),
    273     HWCQDCMModeManager::ActiveFeatureCMD("svi:on", "svi:off", "svi:status", "running"),
    274 };
    275 
    276 const char *const HWCQDCMModeManager::kSocketName = "pps";
    277 const char *const HWCQDCMModeManager::kTagName = "surfaceflinger";
    278 const char *const HWCQDCMModeManager::kPackageName = "colormanager";
    279 
    280 HWCQDCMModeManager *HWCQDCMModeManager::CreateQDCMModeMgr() {
    281   HWCQDCMModeManager *mode_mgr = new HWCQDCMModeManager();
    282 
    283   if (!mode_mgr) {
    284     DLOGW("No memory to create HWCQDCMModeManager.");
    285     return NULL;
    286   } else {
    287     mode_mgr->socket_fd_ =
    288         ::socket_local_client(kSocketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
    289     if (mode_mgr->socket_fd_ < 0) {
    290       // it should not be disastrous and we still can grab wakelock in QDCM mode.
    291       DLOGW("Unable to connect to dpps socket!");
    292     }
    293 
    294     // retrieve system GPU idle timeout value for later to recover.
    295     mode_mgr->entry_timeout_ = UINT32(HWCDebugHandler::GetIdleTimeoutMs());
    296 
    297     // acquire the binder handle to Android system PowerManager for later use.
    298     android::sp<android::IBinder> binder =
    299         android::defaultServiceManager()->checkService(android::String16("power"));
    300     if (binder == NULL) {
    301       DLOGW("Application can't connect to  power manager service");
    302       delete mode_mgr;
    303       mode_mgr = NULL;
    304     } else {
    305       mode_mgr->power_mgr_ = android::interface_cast<android::IPowerManager>(binder);
    306     }
    307   }
    308 
    309   return mode_mgr;
    310 }
    311 
    312 HWCQDCMModeManager::~HWCQDCMModeManager() {
    313   if (socket_fd_ >= 0)
    314     ::close(socket_fd_);
    315 }
    316 
    317 int HWCQDCMModeManager::AcquireAndroidWakeLock(bool enable) {
    318   int ret = 0;
    319 
    320   if (enable) {
    321     if (wakelock_token_ == NULL) {
    322       android::sp<android::IBinder> binder = new android::BBinder();
    323       android::status_t status = power_mgr_->acquireWakeLock(
    324           (kFullWakeLock | kAcquireCauseWakeup | kONAfterRelease), binder,
    325           android::String16(kTagName), android::String16(kPackageName));
    326       if (status == android::NO_ERROR) {
    327         wakelock_token_ = binder;
    328       }
    329     }
    330   } else {
    331     if (wakelock_token_ != NULL && power_mgr_ != NULL) {
    332       power_mgr_->releaseWakeLock(wakelock_token_, 0);
    333       wakelock_token_.clear();
    334       wakelock_token_ = NULL;
    335     }
    336   }
    337 
    338   return ret;
    339 }
    340 
    341 int HWCQDCMModeManager::EnableActiveFeatures(bool enable,
    342                                              const HWCQDCMModeManager::ActiveFeatureCMD &cmds,
    343                                              bool *was_running) {
    344   int ret = 0;
    345   ssize_t size = 0;
    346   char response[kSocketCMDMaxLength] = {
    347       0,
    348   };
    349 
    350   if (socket_fd_ < 0) {
    351     DLOGW("No socket connection available!");
    352     return -EFAULT;
    353   }
    354 
    355   if (!enable) {  // if client requesting to disable it.
    356     // query CABL status, if off, no action. keep the status.
    357     size = ::write(socket_fd_, cmds.cmd_query_status, strlen(cmds.cmd_query_status));
    358     if (size < 0) {
    359       DLOGW("Unable to send data over socket %s", ::strerror(errno));
    360       ret = -EFAULT;
    361     } else {
    362       size = ::read(socket_fd_, response, kSocketCMDMaxLength);
    363       if (size < 0) {
    364         DLOGW("Unable to read data over socket %s", ::strerror(errno));
    365         ret = -EFAULT;
    366       } else if (!strncmp(response, cmds.running, strlen(cmds.running))) {
    367         *was_running = true;
    368       }
    369     }
    370 
    371     if (*was_running) {  // if was running, it's requested to disable it.
    372       size = ::write(socket_fd_, cmds.cmd_off, strlen(cmds.cmd_off));
    373       if (size < 0) {
    374         DLOGW("Unable to send data over socket %s", ::strerror(errno));
    375         ret = -EFAULT;
    376       }
    377     }
    378   } else {  // if was running, need enable it back.
    379     if (*was_running) {
    380       size = ::write(socket_fd_, cmds.cmd_on, strlen(cmds.cmd_on));
    381       if (size < 0) {
    382         DLOGW("Unable to send data over socket %s", ::strerror(errno));
    383         ret = -EFAULT;
    384       }
    385     }
    386   }
    387 
    388   return ret;
    389 }
    390 
    391 int HWCQDCMModeManager::EnableQDCMMode(bool enable, HWCDisplay *hwc_display) {
    392   int ret = 0;
    393 
    394   ret = EnableActiveFeatures((enable ? false : true), kActiveFeatureCMD[kCABLFeature],
    395                              &cabl_was_running_);
    396   ret = AcquireAndroidWakeLock(enable);
    397 
    398   // if enter QDCM mode, disable GPU fallback idle timeout.
    399   if (hwc_display) {
    400     uint32_t timeout = enable ? 0 : entry_timeout_;
    401     hwc_display->SetIdleTimeoutMs(timeout);
    402   }
    403 
    404   return ret;
    405 }
    406 
    407 }  // namespace sdm
    408