Home | History | Annotate | Download | only in fb
      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 <errno.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <math.h>
     34 #include <fcntl.h>
     35 #include <sys/types.h>
     36 #include <sys/resource.h>
     37 #include <sys/prctl.h>
     38 #include <utils/debug.h>
     39 #include <utils/sys.h>
     40 #include <pthread.h>
     41 #include <algorithm>
     42 #include <vector>
     43 #include <map>
     44 #include <utility>
     45 
     46 #include "hw_events.h"
     47 
     48 #define __CLASS__ "HWEvents"
     49 
     50 namespace sdm {
     51 
     52 pollfd HWEvents::InitializePollFd(HWEventData *event_data) {
     53   char node_path[kMaxStringLength] = {0};
     54   char data[kMaxStringLength] = {0};
     55   pollfd poll_fd = {0};
     56   poll_fd.fd = -1;
     57 
     58   if (event_data->event_type == HWEvent::EXIT) {
     59     // Create an eventfd to be used to unblock the poll system call when
     60     // a thread is exiting.
     61     poll_fd.fd = Sys::eventfd_(0, 0);
     62     poll_fd.events |= POLLIN;
     63     exit_fd_ = poll_fd.fd;
     64   } else {
     65     snprintf(node_path, sizeof(node_path), "%s%d/%s", fb_path_, fb_num_,
     66              map_event_to_node_[event_data->event_type]);
     67     poll_fd.fd = Sys::open_(node_path, O_RDONLY);
     68     poll_fd.events |= POLLPRI | POLLERR;
     69   }
     70 
     71   if (poll_fd.fd < 0) {
     72     DLOGW("open failed for display=%d event=%s, error=%s", fb_num_,
     73           map_event_to_node_[event_data->event_type], strerror(errno));
     74     return poll_fd;
     75   }
     76 
     77   // Read once on all fds to clear data on all fds.
     78   Sys::pread_(poll_fd.fd, data , kMaxStringLength, 0);
     79 
     80   return poll_fd;
     81 }
     82 
     83 DisplayError HWEvents::SetEventParser(HWEvent event_type, HWEventData *event_data) {
     84   DisplayError error = kErrorNone;
     85   switch (event_type) {
     86     case HWEvent::VSYNC:
     87       event_data->event_parser = &HWEvents::HandleVSync;
     88       break;
     89     case HWEvent::IDLE_NOTIFY:
     90       event_data->event_parser = &HWEvents::HandleIdleTimeout;
     91       break;
     92     case HWEvent::CEC_READ_MESSAGE:
     93       event_data->event_parser = &HWEvents::HandleCECMessage;
     94       break;
     95     case HWEvent::EXIT:
     96       event_data->event_parser = &HWEvents::HandleThreadExit;
     97       break;
     98     case HWEvent::SHOW_BLANK_EVENT:
     99       event_data->event_parser = &HWEvents::HandleBlank;
    100       break;
    101     case HWEvent::THERMAL_LEVEL:
    102       event_data->event_parser = &HWEvents::HandleThermal;
    103       break;
    104     case HWEvent::IDLE_POWER_COLLAPSE:
    105       event_data->event_parser = &HWEvents::HandleIdlePowerCollapse;
    106       break;
    107     case HWEvent::PINGPONG_TIMEOUT:
    108       event_data->event_parser = &HWEvents::HandlePingPongTimeout;
    109       break;
    110     default:
    111       error = kErrorParameters;
    112       break;
    113   }
    114 
    115   return error;
    116 }
    117 
    118 void HWEvents::PopulateHWEventData() {
    119   for (uint32_t i = 0; i < event_list_.size(); i++) {
    120     HWEventData event_data;
    121     event_data.event_type = event_list_[i];
    122     SetEventParser(event_list_[i], &event_data);
    123     poll_fds_[i] = InitializePollFd(&event_data);
    124     event_data_list_.push_back(event_data);
    125   }
    126 }
    127 
    128 DisplayError HWEvents::Init(int fb_num, HWEventHandler *event_handler,
    129                             const vector<HWEvent> &event_list) {
    130   if (!event_handler)
    131     return kErrorParameters;
    132 
    133   event_handler_ = event_handler;
    134   fb_num_ = fb_num;
    135   event_list_ = event_list;
    136   poll_fds_.resize(event_list_.size());
    137   event_thread_name_ += " - " + std::to_string(fb_num_);
    138   map_event_to_node_ = {{HWEvent::VSYNC, "vsync_event"},
    139                         {HWEvent::EXIT, "thread_exit"},
    140                         {HWEvent::IDLE_NOTIFY, "idle_notify"},
    141                         {HWEvent::SHOW_BLANK_EVENT, "show_blank_event"},
    142                         {HWEvent::CEC_READ_MESSAGE, "cec/rd_msg"},
    143                         {HWEvent::THERMAL_LEVEL, "msm_fb_thermal_level"},
    144                         {HWEvent::IDLE_POWER_COLLAPSE, "idle_power_collapse"},
    145                         {HWEvent::PINGPONG_TIMEOUT, "pingpong_timeout"}};
    146 
    147   PopulateHWEventData();
    148 
    149   if (pthread_create(&event_thread_, NULL, &DisplayEventThread, this) < 0) {
    150     DLOGE("Failed to start %s, error = %s", event_thread_name_.c_str());
    151     return kErrorResources;
    152   }
    153 
    154   return kErrorNone;
    155 }
    156 
    157 DisplayError HWEvents::Deinit() {
    158   exit_threads_ = true;
    159   Sys::pthread_cancel_(event_thread_);
    160 
    161   uint64_t exit_value = 1;
    162   ssize_t write_size = Sys::write_(exit_fd_, &exit_value, sizeof(uint64_t));
    163   if (write_size != sizeof(uint64_t))
    164     DLOGW("Error triggering exit_fd_ (%d). write size = %d, error = %s", exit_fd_, write_size,
    165           strerror(errno));
    166 
    167   pthread_join(event_thread_, NULL);
    168 
    169   for (uint32_t i = 0; i < event_list_.size(); i++) {
    170     Sys::close_(poll_fds_[i].fd);
    171     poll_fds_[i].fd = -1;
    172   }
    173 
    174   return kErrorNone;
    175 }
    176 
    177 void* HWEvents::DisplayEventThread(void *context) {
    178   if (context) {
    179     return reinterpret_cast<HWEvents *>(context)->DisplayEventHandler();
    180   }
    181 
    182   return NULL;
    183 }
    184 
    185 void* HWEvents::DisplayEventHandler() {
    186   char data[kMaxStringLength] = {0};
    187 
    188   prctl(PR_SET_NAME, event_thread_name_.c_str(), 0, 0, 0);
    189   setpriority(PRIO_PROCESS, 0, kThreadPriorityUrgent);
    190 
    191   while (!exit_threads_) {
    192     int error = Sys::poll_(poll_fds_.data(), UINT32(event_list_.size()), -1);
    193 
    194     if (error <= 0) {
    195       DLOGW("poll failed. error = %s", strerror(errno));
    196       continue;
    197     }
    198 
    199     for (uint32_t event = 0; event < event_list_.size(); event++) {
    200       pollfd &poll_fd = poll_fds_[event];
    201 
    202       if (event_list_.at(event) == HWEvent::EXIT) {
    203         if ((poll_fd.revents & POLLIN) && (Sys::read_(poll_fd.fd, data, kMaxStringLength) > 0)) {
    204           (this->*(event_data_list_[event]).event_parser)(data);
    205         }
    206       } else {
    207         if ((poll_fd.revents & POLLPRI) &&
    208                 (Sys::pread_(poll_fd.fd, data, kMaxStringLength, 0) > 0)) {
    209           (this->*(event_data_list_[event]).event_parser)(data);
    210         }
    211       }
    212     }
    213   }
    214 
    215   pthread_exit(0);
    216 
    217   return NULL;
    218 }
    219 
    220 void HWEvents::HandleVSync(char *data) {
    221   int64_t timestamp = 0;
    222   if (!strncmp(data, "VSYNC=", strlen("VSYNC="))) {
    223     timestamp = strtoll(data + strlen("VSYNC="), NULL, 0);
    224   }
    225 
    226   event_handler_->VSync(timestamp);
    227 }
    228 
    229 void HWEvents::HandleIdleTimeout(char *data) {
    230   event_handler_->IdleTimeout();
    231 }
    232 
    233 void HWEvents::HandlePingPongTimeout(char *data) {
    234   event_handler_->PingPongTimeout();
    235 }
    236 
    237 void HWEvents::HandleThermal(char *data) {
    238   int64_t thermal_level = 0;
    239   if (!strncmp(data, "thermal_level=", strlen("thermal_level="))) {
    240     thermal_level = strtoll(data + strlen("thermal_level="), NULL, 0);
    241   }
    242 
    243   DLOGI("Received thermal notification with thermal level = %d", thermal_level);
    244 
    245   event_handler_->ThermalEvent(thermal_level);
    246 }
    247 
    248 void HWEvents::HandleCECMessage(char *data) {
    249   event_handler_->CECMessage(data);
    250 }
    251 
    252 void HWEvents::HandleIdlePowerCollapse(char *data) {
    253   event_handler_->IdlePowerCollapse();
    254 }
    255 
    256 }  // namespace sdm
    257