1 /* 2 * Copyright (C) 2012 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 25 #define LOG_TAG "PowerHAL" 26 #include <utils/Log.h> 27 28 #include <hardware/hardware.h> 29 #include <hardware/power.h> 30 31 #define STATE_ON "state=1" 32 #define STATE_OFF "state=0" 33 34 #define MAX_LENGTH 50 35 #define BOOST_SOCKET "/dev/socket/pb" 36 37 static int client_sockfd; 38 static struct sockaddr_un client_addr; 39 static int last_state = -1; 40 41 static void socket_init() 42 { 43 if (!client_sockfd) { 44 client_sockfd = socket(PF_UNIX, SOCK_DGRAM, 0); 45 if (client_sockfd < 0) { 46 ALOGE("%s: failed to open: %s", __func__, strerror(errno)); 47 return; 48 } 49 memset(&client_addr, 0, sizeof(struct sockaddr_un)); 50 client_addr.sun_family = AF_UNIX; 51 snprintf(client_addr.sun_path, UNIX_PATH_MAX, BOOST_SOCKET); 52 } 53 } 54 55 static void power_init(struct power_module *module) 56 { 57 ALOGI("%s", __func__); 58 socket_init(); 59 } 60 61 static void sync_thread(int off) 62 { 63 int rc; 64 pid_t client; 65 char data[MAX_LENGTH]; 66 67 if (client_sockfd < 0) { 68 ALOGE("%s: boost socket not created", __func__); 69 return; 70 } 71 72 client = getpid(); 73 74 if (!off) { 75 snprintf(data, MAX_LENGTH, "2:%d", client); 76 rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un)); 77 } else { 78 snprintf(data, MAX_LENGTH, "3:%d", client); 79 rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un)); 80 } 81 82 if (rc < 0) { 83 ALOGE("%s: failed to send: %s", __func__, strerror(errno)); 84 } 85 } 86 87 static void process_video_encode_hint(void *metadata) 88 { 89 90 socket_init(); 91 92 if (client_sockfd < 0) { 93 ALOGE("%s: boost socket not created", __func__); 94 return; 95 } 96 97 if (metadata) { 98 if (!strncmp(metadata, STATE_ON, sizeof(STATE_ON))) { 99 /* Video encode started */ 100 sync_thread(1); 101 } else if (!strncmp(metadata, STATE_OFF, sizeof(STATE_OFF))) { 102 /* Video encode stopped */ 103 sync_thread(0); 104 } else 105 return; 106 } else { 107 return; 108 } 109 110 } 111 112 113 static void touch_boost() 114 { 115 int rc; 116 pid_t client; 117 char data[MAX_LENGTH]; 118 119 if (client_sockfd < 0) { 120 ALOGE("%s: boost socket not created", __func__); 121 return; 122 } 123 124 client = getpid(); 125 126 snprintf(data, MAX_LENGTH, "1:%d", client); 127 rc = sendto(client_sockfd, data, strlen(data), 0, (const struct sockaddr *)&client_addr, sizeof(struct sockaddr_un)); 128 if (rc < 0) { 129 ALOGE("%s: failed to send: %s", __func__, strerror(errno)); 130 } 131 } 132 133 static void power_set_interactive(struct power_module *module, int on) 134 { 135 if (last_state == -1) { 136 last_state = on; 137 } else { 138 if (last_state == on) 139 return; 140 else 141 last_state = on; 142 } 143 144 ALOGV("%s %s", __func__, (on ? "ON" : "OFF")); 145 if (on) { 146 sync_thread(0); 147 touch_boost(); 148 } else { 149 sync_thread(1); 150 } 151 } 152 153 static void power_hint(struct power_module *module, power_hint_t hint, 154 void *data) { 155 switch (hint) { 156 case POWER_HINT_INTERACTION: 157 ALOGV("POWER_HINT_INTERACTION"); 158 touch_boost(); 159 break; 160 #if 0 161 case POWER_HINT_VSYNC: 162 ALOGV("POWER_HINT_VSYNC %s", (data ? "ON" : "OFF")); 163 break; 164 #endif 165 case POWER_HINT_VIDEO_ENCODE: 166 process_video_encode_hint(data); 167 break; 168 default: 169 break; 170 } 171 } 172 173 static struct hw_module_methods_t power_module_methods = { 174 .open = NULL, 175 }; 176 177 struct power_module HAL_MODULE_INFO_SYM = { 178 .common = { 179 .tag = HARDWARE_MODULE_TAG, 180 .module_api_version = POWER_MODULE_API_VERSION_0_2, 181 .hal_api_version = HARDWARE_HAL_API_VERSION, 182 .id = POWER_HARDWARE_MODULE_ID, 183 .name = "Qualcomm Power HAL", 184 .author = "The Android Open Source Project", 185 .methods = &power_module_methods, 186 }, 187 188 .init = power_init, 189 .setInteractive = power_set_interactive, 190 .powerHint = power_hint, 191 }; 192