OSDN Git Service

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