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 coresonline(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, "8:%d", client);
     83         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
     84     } else {
     85         snprintf(data, MAX_LENGTH, "7:%d", client);
     86         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
     87     }
     88 
     89     if (rc < 0) {
     90         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
     91     }
     92 }
     93 
     94 static void enc_boost(int off)
     95 {
     96     int rc;
     97     pid_t client;
     98     char data[MAX_LENGTH];
     99 
    100     if (client_sockfd < 0) {
    101         ALOGE("%s: boost socket not created", __func__);
    102         return;
    103     }
    104 
    105     client = getpid();
    106 
    107     if (!off) {
    108         snprintf(data, MAX_LENGTH, "5:%d", client);
    109         rc = sendto(client_sockfd, data, strlen(data), 0,
    110             (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    111     } else {
    112         snprintf(data, MAX_LENGTH, "6:%d", client);
    113         rc = sendto(client_sockfd, data, strlen(data), 0,
    114             (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 process_video_encode_hint(void *metadata)
    123 {
    124 
    125     socket_init();
    126 
    127     if (client_sockfd < 0) {
    128         ALOGE("%s: boost socket not created", __func__);
    129         return;
    130     }
    131 
    132     if (metadata) {
    133         if (!strncmp(metadata, STATE_ON, sizeof(STATE_ON))) {
    134             /* Video encode started */
    135             enc_boost(1);
    136         } else if (!strncmp(metadata, STATE_OFF, sizeof(STATE_OFF))) {
    137             /* Video encode stopped */
    138             enc_boost(0);
    139         }  else if (!strncmp(metadata, STATE_HDR_ON, sizeof(STATE_HDR_ON))) {
    140             /* HDR usecase started */
    141         } else if (!strncmp(metadata, STATE_HDR_OFF, sizeof(STATE_HDR_OFF))) {
    142             /* HDR usecase stopped */
    143         }else
    144             return;
    145     } else {
    146         return;
    147     }
    148 }
    149 
    150 
    151 static void touch_boost()
    152 {
    153     int rc, fd;
    154     pid_t client;
    155     char data[MAX_LENGTH];
    156     char buf[MAX_LENGTH];
    157 
    158     if (client_sockfd < 0) {
    159         ALOGE("%s: boost socket not created", __func__);
    160         return;
    161     }
    162 
    163     client = getpid();
    164 
    165     snprintf(data, MAX_LENGTH, "1:%d", client);
    166     rc = sendto(client_sockfd, data, strlen(data), 0,
    167         (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    168     if (rc < 0) {
    169         ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    170     }
    171 }
    172 
    173 static void low_power(int on)
    174 {
    175     int rc;
    176     pid_t client;
    177     char data[MAX_LENGTH];
    178 
    179     if (client_sockfd < 0) {
    180         ALOGE("%s: boost socket not created", __func__);
    181         return;
    182     }
    183 
    184     client = getpid();
    185 
    186     if (on) {
    187         snprintf(data, MAX_LENGTH, "10:%d", client);
    188         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    189         if (rc < 0) {
    190             ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    191         }
    192     } else {
    193         snprintf(data, MAX_LENGTH, "9:%d", client);
    194         rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un));
    195         if (rc < 0) {
    196             ALOGE("%s: failed to send: %s", __func__, strerror(errno));
    197         }
    198     }
    199 }
    200 
    201 static void process_low_power_hint(void* data)
    202 {
    203     int on = (long) data;
    204     if (client_sockfd < 0) {
    205         ALOGE("%s: boost socket not created", __func__);
    206         return;
    207     }
    208 
    209     low_power(on);
    210 }
    211 
    212 static void power_set_interactive(__attribute__((unused)) struct power_module *module, int on)
    213 {
    214     if (last_state == -1) {
    215         last_state = on;
    216     } else {
    217         if (last_state == on)
    218             return;
    219         else
    220             last_state = on;
    221     }
    222 
    223     ALOGV("%s %s", __func__, (on ? "ON" : "OFF"));
    224     if (on) {
    225         coresonline(0);
    226         touch_boost();
    227     } else {
    228         coresonline(1);
    229     }
    230 }
    231 
    232 static void power_hint( __attribute__((unused)) struct power_module *module,
    233                         __attribute__((unused)) power_hint_t hint,
    234                         __attribute__((unused)) void *data)
    235 {
    236     switch (hint) {
    237         case POWER_HINT_INTERACTION:
    238             ALOGV("POWER_HINT_INTERACTION");
    239             touch_boost();
    240             break;
    241 #if 0
    242         case POWER_HINT_VSYNC:
    243             ALOGV("POWER_HINT_VSYNC %s", (data ? "ON" : "OFF"));
    244             break;
    245 #endif
    246         case POWER_HINT_VIDEO_ENCODE:
    247             process_video_encode_hint(data);
    248             break;
    249         case POWER_HINT_LOW_POWER:
    250              process_low_power_hint(data);
    251              break;
    252         default:
    253              break;
    254     }
    255 }
    256 
    257 static struct hw_module_methods_t power_module_methods = {
    258     .open = NULL,
    259 };
    260 
    261 struct power_module HAL_MODULE_INFO_SYM = {
    262     .common = {
    263         .tag = HARDWARE_MODULE_TAG,
    264         .module_api_version = POWER_MODULE_API_VERSION_0_2,
    265         .hal_api_version = HARDWARE_HAL_API_VERSION,
    266         .id = POWER_HARDWARE_MODULE_ID,
    267         .name = "Shamu Power HAL",
    268         .author = "The Android Open Source Project",
    269         .methods = &power_module_methods,
    270     },
    271 
    272     .init = power_init,
    273     .setInteractive = power_set_interactive,
    274     .powerHint = power_hint,
    275 };
    276