• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
socket_init()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 
power_init(struct power_module * module)62 static void power_init(__attribute__((unused)) struct power_module *module)
63 {
64     ALOGI("%s", __func__);
65     socket_init();
66 }
67 
sync_thread(int off)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 
coresonline(int off)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 
enc_boost(int off)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 
process_video_encode_hint(void * metadata)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 
touch_boost()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 
low_power(int on)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 
process_low_power_hint(void * data)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 
power_set_interactive(struct power_module * module,int on)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 
power_hint(struct power_module * module,power_hint_t hint,void * data)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