Home | History | Annotate | Download | only in power
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <errno.h>
     17 #include <string.h>
     18 #include <sys/types.h>
     19 #include <sys/stat.h>
     20 #include <sys/socket.h>
     21 #include <sys/un.h>
     22 #include <fcntl.h>
     23 #include <dlfcn.h>
     24 #include <cutils/uevent.h>
     25 #include <errno.h>
     26 #include <sys/poll.h>
     27 #include <pthread.h>
     28 #include <linux/netlink.h>
     29 #include <stdlib.h>
     30 #include <stdbool.h>
     31 
     32 #define LOG_TAG "PowerHAL"
     33 #include <utils/Log.h>
     34 
     35 #include <hardware/hardware.h>
     36 #include <hardware/power.h>
     37 
     38 #define STATE_ON "state=1"
     39 #define STATE_OFF "state=0"
     40 #define STATE_HDR_ON "state=2"
     41 #define STATE_HDR_OFF "state=3"
     42 #define MAX_LENGTH         50
     43 #define BOOST_SOCKET       "/dev/socket/mpdecision/pb"
     44 static int client_sockfd;
     45 static struct sockaddr_un client_addr;
     46 static int last_state = -1;
     47 
     48 static void socket_init()
     49 {
     50     if (!client_sockfd) {
     51         client_sockfd = socket(PF_UNIX, SOCK_DGRAM, 0);
     52         if (client_sockfd < 0) {
     53             ALOGE("%s: failed to open: %s", __func__, strerror(errno));
     54             return;
     55         }
     56         memset(&client_addr, 0, sizeof(struct sockaddr_un));
     57         client_addr.sun_family = AF_UNIX;
     58         snprintf(client_addr.sun_path, UNIX_PATH_MAX, BOOST_SOCKET);
     59     }
     60 }
     61 
     62 static void power_init(__attribute__((unused)) struct power_module *module)
     63 {
     64     ALOGI("%s", __func__);
     65     socket_init();
     66 }
     67 
     68 static void sync_thread(int off)
     69 {
     70     int rc;
     71     pid_t client;
     72     char data[MAX_LENGTH];
     73 
     74     if (client_sockfd < 0) {
     75         ALOGE("%s: boost socket not created", __func__);
     76         return;
     77     }
     78 
     79     client = getpid();
     80 
     81     if (!off) {
     82         snprintf(data, MAX_LENGTH, "2:%d", client);
     83         rc = sendto(client_sockfd, data, strlen(data), 0,
     84             (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
     85     } else {
     86         snprintf(data, MAX_LENGTH, "3:%d", client);
     87         rc = sendto(client_sockfd, data, strlen(data), 0,
     88             (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
     89     }
     90 
     91     if (rc < 0) {
     92         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
     93     }
     94 }
     95 
     96 static void coresonline(int off)
     97 {
     98     int rc;
     99     pid_t client;
    100     char data[MAX_LENGTH];
    101 
    102     if (client_sockfd < 0) {
    103         ALOGE("%s: boost socket not created", __func__);
    104         return;
    105     }
    106 
    107     client = getpid();
    108 
    109     if (!off) {
    110         snprintf(data, MAX_LENGTH, "8:%d", client);
    111         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    112     } else {
    113         snprintf(data, MAX_LENGTH, "7:%d", client);
    114         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    115     }
    116 
    117     if (rc < 0) {
    118         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    119     }
    120 }
    121 
    122 static void enc_boost(int off)
    123 {
    124     int rc;
    125     pid_t client;
    126     char data[MAX_LENGTH];
    127 
    128     if (client_sockfd < 0) {
    129         ALOGE("%s: boost socket not created", __func__);
    130         return;
    131     }
    132 
    133     client = getpid();
    134 
    135     if (!off) {
    136         snprintf(data, MAX_LENGTH, "5:%d", client);
    137         rc = sendto(client_sockfd, data, strlen(data), 0,
    138             (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    139     } else {
    140         snprintf(data, MAX_LENGTH, "6:%d", client);
    141         rc = sendto(client_sockfd, data, strlen(data), 0,
    142             (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    143     }
    144 
    145     if (rc < 0) {
    146         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    147     }
    148 }
    149 
    150 static void process_video_encode_hint(void *metadata)
    151 {
    152 
    153     socket_init();
    154 
    155     if (client_sockfd < 0) {
    156         ALOGE("%s: boost socket not created", __func__);
    157         return;
    158     }
    159 
    160     if (metadata) {
    161         if (!strncmp(metadata, STATE_ON, sizeof(STATE_ON))) {
    162             /* Video encode started */
    163             sync_thread(1);
    164             enc_boost(1);
    165         } else if (!strncmp(metadata, STATE_OFF, sizeof(STATE_OFF))) {
    166             /* Video encode stopped */
    167             sync_thread(0);
    168             enc_boost(0);
    169         }  else if (!strncmp(metadata, STATE_HDR_ON, sizeof(STATE_HDR_ON))) {
    170             /* HDR usecase started */
    171         } else if (!strncmp(metadata, STATE_HDR_OFF, sizeof(STATE_HDR_OFF))) {
    172             /* HDR usecase stopped */
    173         }else
    174             return;
    175     } else {
    176         return;
    177     }
    178 }
    179 
    180 
    181 static void touch_boost()
    182 {
    183     int rc, fd;
    184     pid_t client;
    185     char data[MAX_LENGTH];
    186     char buf[MAX_LENGTH];
    187 
    188     if (client_sockfd < 0) {
    189         ALOGE("%s: boost socket not created", __func__);
    190         return;
    191     }
    192 
    193     client = getpid();
    194 
    195     snprintf(data, MAX_LENGTH, "1:%d", client);
    196     rc = sendto(client_sockfd, data, strlen(data), 0,
    197         (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    198     if (rc < 0) {
    199         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    200     }
    201 }
    202 
    203 static void low_power(int on)
    204 {
    205     int rc;
    206     pid_t client;
    207     char data[MAX_LENGTH];
    208 
    209     if (client_sockfd < 0) {
    210         ALOGE("%s: boost socket not created", __func__);
    211         return;
    212     }
    213 
    214     client = getpid();
    215 
    216     if (on) {
    217         snprintf(data, MAX_LENGTH, "10:%d", client);
    218         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    219         if (rc < 0) {
    220             ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    221         }
    222     } else {
    223         snprintf(data, MAX_LENGTH, "9:%d", client);
    224         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    225         if (rc < 0) {
    226             ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    227         }
    228     }
    229 }
    230 
    231 static void process_low_power_hint(void* data)
    232 {
    233     int on = (long) data;
    234     if (client_sockfd < 0) {
    235         ALOGE("%s: boost socket not created", __func__);
    236         return;
    237     }
    238 
    239     low_power(on);
    240 }
    241 
    242 static void power_set_interactive(__attribute__((unused)) struct power_module *module, int on)
    243 {
    244     if (last_state == -1) {
    245         last_state = on;
    246     } else {
    247         if (last_state == on)
    248             return;
    249         else
    250             last_state = on;
    251     }
    252 
    253     ALOGV("%s %s", __func__, (on ? "ON" : "OFF"));
    254     if (on) {
    255         coresonline(0);
    256         sync_thread(0);
    257         touch_boost();
    258     } else {
    259         sync_thread(1);
    260         coresonline(1);
    261     }
    262 }
    263 
    264 static void power_hint( __attribute__((unused)) struct power_module *module,
    265                         __attribute__((unused)) power_hint_t hint,
    266                         __attribute__((unused)) void *data)
    267 {
    268     switch (hint) {
    269         case POWER_HINT_INTERACTION:
    270             ALOGV("POWER_HINT_INTERACTION");
    271             touch_boost();
    272             break;
    273 #if 0
    274         case POWER_HINT_VSYNC:
    275             ALOGV("POWER_HINT_VSYNC %s", (data ? "ON" : "OFF"));
    276             break;
    277 #endif
    278         case POWER_HINT_VIDEO_ENCODE:
    279             process_video_encode_hint(data);
    280             break;
    281         case POWER_HINT_LOW_POWER:
    282              process_low_power_hint(data);
    283              break;
    284         default:
    285              break;
    286     }
    287 }
    288 
    289 static struct hw_module_methods_t power_module_methods = {
    290     .open = NULL,
    291 };
    292 
    293 struct power_module HAL_MODULE_INFO_SYM = {
    294     .common = {
    295         .tag = HARDWARE_MODULE_TAG,
    296         .module_api_version = POWER_MODULE_API_VERSION_0_2,
    297         .hal_api_version = HARDWARE_HAL_API_VERSION,
    298         .id = POWER_HARDWARE_MODULE_ID,
    299         .name = "Shamu Power HAL",
    300         .author = "The Android Open Source Project",
    301         .methods = &power_module_methods,
    302     },
    303 
    304     .init = power_init,
    305     .setInteractive = power_set_interactive,
    306     .powerHint = power_hint,
    307 };
    308