OSDN Git Service

Merge branch 'lineage-16.0' of https://github.com/me176c-dev/android_hardware_iio...
[android-x86/hardware-intel-libsensors.git] / activity.c
1 /*
2 // Copyright (c) 2015 Intel Corporation
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
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <dlfcn.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <errno.h>
26 #include <hardware/activity_recognition.h>
27 #include <hardware/sensors.h>
28 #include <utils/Log.h>
29
30 #include "activity_event_utils.h"
31
32 /* Return error codes */
33 #define ARGV_ERR        1
34 #define HAL_ACCESS_ERR  1
35 #define HAL_OPEN_ERR    2
36 #define HAL_SYMBOL_ERR  3
37
38 #define START_CMD               "start"
39 #define STOP_CMD                "stop"
40 #define REGISTER_CMD            "register_callback"
41 #define ENABLE_CMD              "enable"
42 #define DISABLE_CMD             "disable"
43 #define LIST_CMD                "list"
44 #define FLUSH_CMD               "flush"
45 #define MONITOR_START_CMD       "monitor_start"
46 #define MONITOR_STOP_CMD        "monitor_stop"
47
48 #define MAX_CMD_SIZE    512
49 #define MAX_ARGS        8
50
51 #define CMD_SEPARATOR   " "
52
53 #define ACK_FLAG                1
54 #define MONITOR_START_FLAG      2
55 #define MONITOR_STOP_FLAG       3
56
57 /* We define a default latency since current HAL does not use this latency */
58 #define DEFAULT_LATENCY 0
59
60 static struct activity_recognition_module *hmi;
61 static struct hw_device_t *device;
62
63 static FILE *client, *monitor_client;
64 static int monitor_connection = -1;
65
66 #ifdef ANDROID
67 #define ACTIVITY_SERVER_NAME    "/dev/socket/activity-server"
68 #else
69 #define ACTIVITY_SERVER_NAME    "/tmp/activity-server"
70 #endif
71
72 #define CLIENT_ERR(f, fmt...)                                   \
73          { if (f) { fprintf(f, fmt); fprintf(f, "\n"); } ALOGE(fmt); }
74
75 struct sockaddr_un server_addr = {
76         .sun_family     = AF_UNIX,
77         .sun_path       = ACTIVITY_SERVER_NAME,
78 };
79
80 /* Event types are indexed so that a type is positioned at an index represented
81  * by its value in the ACTIVITY_TYPE_* enum in activity_recognition.h .
82  */
83 static const char* event_types[] = {
84         "FLUSH_COMPLETE",
85         "ENTER",
86         "EXIT",
87 };
88
89 static void dummy_activity_callback(const activity_recognition_callback_procs_t *procs __attribute((unused)),
90                                     const activity_event_t *events, int count)
91 {
92         int i;
93
94         /* Exit if nobody is monitoring */
95         if (monitor_client == NULL)
96                 return;
97
98         fprintf(monitor_client, "No. of activity events: %d\n", count);
99
100         for (i = 0; i < count; i++)
101                 fprintf(monitor_client, "\t<activity [%d], event %s> occurred at %lld (ns)\n",
102                         events[i].activity,
103                         event_types[events[i].event_type],
104                         events[i].timestamp);
105 }
106
107 static activity_recognition_callback_procs_t dummy_callback_procs = {
108         .activity_callback = dummy_activity_callback
109 };
110
111 /* We register a dummy callback that just prints the events reported from HAL. */
112 static void register_activity_callback(void)
113 {
114         struct activity_recognition_device *activity_dev =
115                 (struct activity_recognition_device *) device;
116
117         activity_dev->register_activity_callback(activity_dev, &dummy_callback_procs);
118 }
119
120 static int enable_activity_event(uint32_t handle, uint32_t event_type)
121 {
122         struct activity_recognition_device *activity_dev =
123                 (struct activity_recognition_device *) device;
124
125         return activity_dev->enable_activity_event(activity_dev, handle,
126                                                    event_type, DEFAULT_LATENCY);
127 }
128
129 static int disable_activity_event(uint32_t handle, uint32_t event_type)
130 {
131         struct activity_recognition_device *activity_dev =
132                 (struct activity_recognition_device*) device;
133
134         return activity_dev->disable_activity_event(activity_dev, handle, event_type);
135 }
136
137 static int flush(void)
138 {
139         struct activity_recognition_device *activity_dev =
140                 (struct activity_recognition_device *) device;
141
142         return activity_dev->flush(activity_dev);
143 }
144
145 static int print_usage(void)
146 {
147         fprintf(stderr, "Program usage:\n");
148         fprintf(stderr, "\tactivity %s\n", START_CMD);
149         fprintf(stderr, "\tactivity %s\n", STOP_CMD);
150         fprintf(stderr, "\tactivity %s\n", REGISTER_CMD);
151         fprintf(stderr, "\tactivity %s\n", LIST_CMD);
152         fprintf(stderr, "\tactivity %s <activity_id> <event_type>\n", ENABLE_CMD);
153         fprintf(stderr, "\tactivity %s <activity_id> <event_type>\n", DISABLE_CMD);
154         fprintf(stderr, "\tactivity %s\n", FLUSH_CMD);
155         fprintf(stderr, "\tactivity %s\n", MONITOR_START_CMD);
156         fprintf(stderr, "\tactivity %s\n", MONITOR_STOP_CMD);
157         fprintf(stderr, "\t* <activity_id> is the index of the activity as shown by running \"activity list\"\n");
158         fprintf(stderr, "\t* <event_type> is one of the following:\n");
159         fprintf(stderr, "\t\t%d => activity event ENTER\n", ACTIVITY_EVENT_ENTER);
160         fprintf(stderr, "\t\t%d => activity event EXIT\n", ACTIVITY_EVENT_EXIT);
161         fprintf(stderr, "\t\t%d => activity event FLUSH COMPLETE\n", ACTIVITY_EVENT_FLUSH_COMPLETE);
162
163         return ARGV_ERR;
164 }
165
166 static int parse_cmd(char buffer[])
167 {
168         char *tmp, *args[MAX_ARGS];
169         int count;
170
171         tmp = strtok(buffer, CMD_SEPARATOR);
172         count = 0;
173         while (tmp) {
174                 args[count++]   = tmp;
175                 tmp             = strtok(NULL, CMD_SEPARATOR);
176         }
177
178         if (!count) {
179                 CLIENT_ERR(client, "Invalid command %s", buffer);
180                 return -1;
181         }
182
183         if (strncmp(args[0], STOP_CMD, sizeof(STOP_CMD)) == 0) {
184                 if (count != 1) {
185                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
186                                    'activity %s'", STOP_CMD);
187                 } else {
188                         fprintf(client, "Stopping server\n");
189                         fflush(client);
190                 }
191
192                 unlink(ACTIVITY_SERVER_NAME);
193
194                 exit(EXIT_SUCCESS);
195         }
196
197         if (strncmp(args[0], LIST_CMD, sizeof(LIST_CMD)) == 0) {
198                 const char * const* activities;
199                 int size, i;
200
201                 if (count != 1)
202                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
203                                    'activity %s'", LIST_CMD);
204                 size = hmi->get_supported_activities_list(hmi, &activities);
205                 if (client) {
206                         fprintf(client, "Activities list:\n");
207                         for (i = 0; i < size; i++)
208                                 fprintf(client, "\t[%d] %s\n", i + 1, activities[i]);
209                 }
210
211                 return 0;
212         }
213
214         if (strncmp(args[0], REGISTER_CMD, sizeof(REGISTER_CMD)) == 0) {
215                 if (count != 1)
216                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
217                                    'activity %s'", REGISTER_CMD);
218                 register_activity_callback();
219
220                 return 0;
221         }
222
223         if (strncmp(args[0], ENABLE_CMD, sizeof(ENABLE_CMD)) == 0) {
224                 if (count > 3)
225                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
226                                    'activity %s %s %s'", ENABLE_CMD, args[1], args[2])
227                 else if (count != 3) {
228                         CLIENT_ERR(client, "Insufficient arguments. Command should be \
229                                    'activity %s <activity_handle> <event_type>'", ENABLE_CMD);
230                         return -1;
231                 }
232
233                 return enable_activity_event(atoi(args[1]), atoi(args[2]));
234         }
235
236         if (strncmp(args[0], DISABLE_CMD, sizeof(DISABLE_CMD)) == 0) {
237                 if (count > 3)
238                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
239                                    'activity %s %s %s'", DISABLE_CMD, args[1], args[2])
240                 else if (count != 3) {
241                         CLIENT_ERR(client, "Insufficient arguments. Command should be \
242                                    'activity %s <activity_handle> <event_type>'", DISABLE_CMD);
243                         return -1;
244                 }
245
246                 return disable_activity_event(atoi(args[1]), atoi(args[2]));
247         }
248
249         if (strncmp(args[0], FLUSH_CMD, sizeof(FLUSH_CMD)) == 0) {
250                 if (count != 1)
251                         CLIENT_ERR(client, "Too many arguments. Trimming command down to \
252                                    'activity %s'", FLUSH_CMD);
253
254                 return flush();
255         }
256
257         if (strncmp(args[0], MONITOR_START_CMD, sizeof(MONITOR_START_CMD)) == 0) {
258                 if (count != 1)
259                         CLIENT_ERR(client, "Too many arguments. Trimming command \
260                                    down to 'activity %s'", MONITOR_START_CMD);
261                 return MONITOR_START_FLAG;
262         }
263
264         if (strncmp(args[0], MONITOR_STOP_CMD, sizeof(MONITOR_STOP_CMD)) == 0) {
265                 if (count != 1)
266                         CLIENT_ERR(client, "Too many arguments. Trimming command \
267                                    down to 'activity %s'", MONITOR_STOP_CMD);
268                 return MONITOR_STOP_FLAG;
269         }
270
271         CLIENT_ERR(client, "Invalid command %s", buffer);
272
273         return -1;
274 }
275
276 static void stop_monitoring(int *flag)
277 {
278         int current_flag = ACK_FLAG;
279
280         /* Send ACK to client */
281         write(monitor_connection, &current_flag, sizeof(current_flag));
282
283         /* Cleanup */
284         fclose(monitor_client);
285         close(monitor_connection);
286         monitor_client          = NULL;
287         monitor_connection      = -1;
288
289         *flag = ACK_FLAG;
290 }
291
292 static void start_monitoring(int conn, int *flag)
293 {
294         /* Stop other started monitor if that's the case */
295         if (monitor_client != NULL)
296                 stop_monitoring(flag);
297
298         monitor_client          = client;
299         monitor_connection      = conn;
300         *flag                   = MONITOR_START_FLAG;
301
302 }
303
304 static void start_server(void)
305 {
306         int sock, conn, ret;
307         int flag;
308
309         /* Just to make sure we do not have more than one server instance */
310         unlink(ACTIVITY_SERVER_NAME);
311
312         sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
313         if (sock == -1) {
314                 ALOGE("Error %s creating socket\n", strerror(errno));
315                 exit(1);
316         }
317
318         ret = bind(sock, (struct sockaddr *) &server_addr, sizeof(server_addr));
319         if (ret == -1) {
320                 ALOGE("Error %s binding socket\n", strerror(errno));
321                 exit(1);
322         }
323
324         ret = listen(sock, 1);
325         if (ret == -1)
326                 ALOGW("Error %s setting socket to listening state\n", strerror(errno));
327
328         /* Accept commands and send them to HAL */
329         while (1) {
330                 char buffer[526], cmsg_buffer[526];
331                 struct sockaddr_un from;
332                 struct iovec recv_buff = {
333                         .iov_base       = buffer,
334                         .iov_len        = sizeof(buffer),
335                 };
336                 struct msghdr msg = {
337                         .msg_name       = &from,
338                         .msg_namelen    = sizeof(from),
339                         .msg_iov        = &recv_buff,
340                         .msg_iovlen     = 1,
341                         .msg_control    = cmsg_buffer,
342                         .msg_controllen = sizeof(cmsg_buffer),
343                 };
344                 struct cmsghdr *cmsg;
345                 bool close_now = true;
346
347                 conn = accept(sock, NULL, NULL);
348                 if (conn == -1) {
349                         ALOGE("Error %s accepting connection\n", strerror(errno));
350                         continue;
351                 }
352
353                 ret = recvmsg(conn, &msg, 0);
354                 if (ret == -1) {
355                         ALOGE("Error %s in receiving message, conn = %d\n", strerror(errno), conn);
356                         close(conn);
357
358                         continue;
359                 }
360
361                 if (!ret)
362                         continue;
363
364                 /* Check for shutdown from the peer */
365                 if (ret == 0)
366                         break;
367
368                 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
369                         if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
370                                 int *received_fd = (int *)CMSG_DATA(cmsg);
371                                 client = fdopen(*received_fd, "w");
372                                 break;
373                         }
374                 }
375
376                 ret = parse_cmd(buffer);
377                 if (ret < 0) {
378                         close(conn);
379                         continue;
380                 }
381                 if (ret == MONITOR_START_FLAG) {
382                         start_monitoring(conn, &flag);
383                         close_now = false;
384                 } else if (ret == MONITOR_STOP_FLAG)
385                         stop_monitoring(&flag);
386                 else
387                         flag = ACK_FLAG;
388
389                 /* Confirm succesfull dispatch */
390                 write(conn, &flag, sizeof(flag));
391
392                 if (close_now) {
393                         fclose(client);
394                         close(conn);
395                 }
396         }
397 }
398
399 static const char *hal_paths[] ={
400         "./activity.gmin.so",
401         "/lib/activity.gmin.so",
402         "/system/lib/hw/activity.gmin.so",
403 };
404
405 static int start_hal(void)
406 {
407         void *hal;
408         int i, ret, no_paths;
409         const char *path = NULL;
410         pid_t child;
411
412         no_paths = sizeof(hal_paths)/sizeof(const char*);
413         for (i = 0; i < no_paths; i++) {
414                 if (access(hal_paths[i], R_OK) == 0) {
415                         path = hal_paths[i];
416                         break;
417                 }
418         }
419
420         if (!path) {
421                 fprintf(stderr, "Unable to find HAL\n");
422                 exit(1);
423         }
424
425         hal = dlopen(path, RTLD_NOW);
426         if (!hal) {
427                 fprintf(stderr, "Error \"%s\" opening activity HAL\n", dlerror());
428                 return HAL_OPEN_ERR;
429         }
430
431         hmi = dlsym(hal, HAL_MODULE_INFO_SYM_AS_STR);
432         if (!hmi) {
433                 fprintf(stderr, "Error \"%s\" finding entry symbol\n", dlerror());
434                 return HAL_SYMBOL_ERR;
435         }
436
437         printf("Activity HAL loaded: name %s vendor %s version %d.%d id %s\n",
438                hmi->common.name, hmi->common.author,
439                hmi->common.version_major, hmi->common.version_minor,
440                hmi->common.id);
441
442         /* Daemonize it */
443         child = fork();
444         if (child) {
445                 usleep(100);
446                 return 0;
447         }
448
449         if (setsid() == (pid_t)-1) {
450                 fprintf(stderr, "failed to send process to background\n");
451                 exit(1);
452         }
453
454         /* Close stdio */
455         close(0); close(1); close(2);
456
457         ALOGI("Proceeding to HAL initialization\n");
458
459         ret = hmi->common.methods->open((struct hw_module_t *) hmi,
460                                         ACTIVITY_RECOGNITION_HARDWARE_INTERFACE,
461                                         &device);
462         if (ret) {
463                 ALOGE("Error %d occurred at HAL module opening\n", ret);
464                 exit(1);
465         }
466
467         start_server();
468
469         return 0;
470 }
471
472 static int send_cmd(int argc, char **argv)
473 {
474         char cmd[MAX_CMD_SIZE];
475         int i, sock, ret, flag;
476         struct iovec rcv_buffer = {
477                 .iov_base       = cmd,
478                 .iov_len        = sizeof(cmd) + 1,
479         };
480         struct cmsg_fd {
481                 struct cmsghdr hdr;
482                 int fd;
483         } cmsg_buff = {
484                 .hdr = {
485                         .cmsg_level     = SOL_SOCKET,
486                         .cmsg_type      = SCM_RIGHTS,
487                         .cmsg_len       = CMSG_LEN(sizeof(int)),
488                 },
489                 .fd = 1,
490         };
491         struct msghdr msg = {
492                 .msg_name       = NULL,
493                 .msg_namelen    = 0,
494                 .msg_iov        = &rcv_buffer,
495                 .msg_iovlen     = 1,
496                 .msg_control    = &cmsg_buff,
497                 .msg_controllen = sizeof(cmsg_buff),
498         };
499
500         strcpy(cmd, argv[1]);
501         for (i = 2; i < argc; i++) {
502                 strncat(cmd, CMD_SEPARATOR, sizeof(CMD_SEPARATOR));
503                 strcat(cmd, argv[i]);
504         }
505
506         sock = socket(AF_UNIX, SOCK_SEQPACKET, 0);
507         if (sock == -1) {
508                 fprintf(stderr, "Error \"%s\" creating socket\n", strerror(errno));
509                 return errno;
510         }
511
512         ret = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
513         if (ret == -1) {
514                 fprintf(stderr, "Error \"%s\" connecting to server\n", strerror(errno));
515                 return errno;
516         }
517
518         ret = sendmsg(sock, &msg, 0);
519         if (ret == -1) {
520                 fprintf(stderr, "Error \"%s\" sending message to server\n", strerror(errno));
521                 return errno;
522         }
523
524         ret = read(sock, &flag, sizeof(flag));
525         if (ret == -1) {
526                 fprintf(stderr, "Error \"%s\" getting answer from server\n", strerror(errno));
527                 return errno;
528         }
529
530         /* Check for ACK or monitoring */
531         if (flag == MONITOR_START_FLAG) {
532                 do {
533                         ret = read(sock, &flag, sizeof(flag));
534                 } while (ret > 0 && flag != ACK_FLAG);
535         } else if (flag != ACK_FLAG)
536                 fprintf(stderr, "Error answer from HAL server: %d. Check logs for more details\n", flag);
537
538         close(sock);
539
540         return 0;
541 }
542
543 static int run_cmd(int argc, char **argv)
544 {
545         if (strncmp(argv[1], START_CMD, sizeof(START_CMD)) == 0) {
546                 if (argc == 2)
547                         return start_hal();
548                 return print_usage();
549         }
550
551         /* Send user command to HAL server socket */
552         return send_cmd(argc, argv);
553 }
554
555 int main(int argc, char **argv)
556 {
557         if (argc < 2)
558                 return print_usage();
559
560         return run_cmd(argc, argv);
561 }