Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / system-emulator.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2013-2014  Intel Corporation. All rights reserved.
6  *
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2.1 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <libgen.h>
35 #include <poll.h>
36 #include <sys/wait.h>
37 #include <sys/param.h>
38 #include <sys/socket.h>
39 #include <sys/un.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 #ifndef WAIT_ANY
44 #define WAIT_ANY (-1)
45 #endif
46
47 #include "src/shared/mainloop.h"
48
49 static char exec_dir[PATH_MAX];
50
51 static pid_t daemon_pid = -1;
52 static pid_t snoop_pid = -1;
53
54 static void run_valgrind(char *prg_name)
55 {
56         char *prg_argv[6];
57         char *prg_envp[3];
58
59         prg_argv[0] = "/usr/bin/valgrind";
60         prg_argv[1] = "--leak-check=full";
61         prg_argv[2] = "--track-origins=yes";
62         prg_argv[3] = prg_name;
63         prg_argv[4] = "-d";
64         prg_argv[5] = NULL;
65
66         prg_envp[0] = "G_SLICE=always-malloc";
67         prg_envp[1] = "G_DEBUG=gc-friendly";
68         prg_envp[2] = NULL;
69
70         execve(prg_argv[0], prg_argv, prg_envp);
71 }
72
73 static void run_bluetoothd(char *prg_name)
74 {
75         char *prg_argv[3];
76         char *prg_envp[1];
77
78         prg_argv[0] = prg_name;
79         prg_argv[1] = "-d";
80         prg_argv[2] = NULL;
81
82         prg_envp[0] = NULL;
83
84         execve(prg_argv[0], prg_argv, prg_envp);
85 }
86
87 static void ctl_start(void)
88 {
89         char prg_name[PATH_MAX];
90         pid_t pid;
91
92         snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir, "bluetoothd");
93
94         printf("Starting %s\n", prg_name);
95
96         pid = fork();
97         if (pid < 0) {
98                 perror("Failed to fork new process");
99                 return;
100         }
101
102         if (pid == 0) {
103                 run_valgrind(prg_name);
104
105                 /* Fallback to no valgrind if running with valgind failed */
106                 run_bluetoothd(prg_name);
107                 exit(0);
108         }
109
110         printf("New process %d created\n", pid);
111
112         daemon_pid = pid;
113 }
114
115 static void snoop_start(void)
116 {
117         char prg_name[PATH_MAX];
118         char *prg_argv[3];
119         char *prg_envp[1];
120         pid_t pid;
121
122         snprintf(prg_name, sizeof(prg_name), "%s/%s", exec_dir,
123                                                         "bluetoothd-snoop");
124
125         prg_argv[0] = prg_name;
126         prg_argv[1] = "/tmp/btsnoop_hci.log";
127         prg_argv[2] = NULL;
128
129         prg_envp[0] = NULL;
130
131         printf("Starting %s\n", prg_name);
132
133         pid = fork();
134         if (pid < 0) {
135                 perror("Failed to fork new process");
136                 return;
137         }
138
139         if (pid == 0) {
140                 execve(prg_argv[0], prg_argv, prg_envp);
141                 exit(0);
142         }
143
144         printf("New process %d created\n", pid);
145
146         snoop_pid = pid;
147 }
148
149 static void snoop_stop(void)
150 {
151         printf("Stoping %s/%s\n", exec_dir, "bluetoothd-snoop");
152
153         kill(snoop_pid, SIGTERM);
154 }
155
156 static void system_socket_callback(int fd, uint32_t events, void *user_data)
157 {
158         char buf[4096];
159         ssize_t len;
160
161         if (events & (EPOLLERR | EPOLLHUP)) {
162                 mainloop_remove_fd(fd);
163                 return;
164         }
165
166         len = read(fd, buf, sizeof(buf));
167         if (len < 0)
168                 return;
169
170         printf("Received %s\n", buf);
171
172         if (!strcmp(buf, "bluetooth.start=daemon")) {
173                 if (daemon_pid > 0)
174                         return;
175
176                 ctl_start();
177         } else if (!strcmp(buf, "bluetooth.start=snoop")) {
178                 if (snoop_pid > 0)
179                         return;
180
181                 snoop_start();
182         } else if (!strcmp(buf, "bluetooth.stop=snoop")) {
183                 if (snoop_pid > 0)
184                         snoop_stop();
185         }
186 }
187
188 static void signal_callback(int signum, void *user_data)
189 {
190         switch (signum) {
191         case SIGINT:
192         case SIGTERM:
193                 mainloop_quit();
194                 break;
195         case SIGCHLD:
196                 while (1) {
197                         pid_t pid;
198                         int status;
199
200                         pid = waitpid(WAIT_ANY, &status, WNOHANG);
201                         if (pid < 0 || pid == 0)
202                                 break;
203
204                         printf("Process %d terminated with status=%d\n",
205                                                                 pid, status);
206
207                         if (pid == daemon_pid)
208                                 daemon_pid = -1;
209                         else if (pid == snoop_pid)
210                                 snoop_pid = -1;
211                 }
212                 break;
213         }
214 }
215
216 int main(int argc, char *argv[])
217 {
218         const char SYSTEM_SOCKET_PATH[] = "\0android_system";
219         sigset_t mask;
220         struct sockaddr_un addr;
221         int fd;
222
223         mainloop_init();
224
225         sigemptyset(&mask);
226         sigaddset(&mask, SIGINT);
227         sigaddset(&mask, SIGTERM);
228         sigaddset(&mask, SIGCHLD);
229
230         mainloop_set_signal(&mask, signal_callback, NULL, NULL);
231
232         printf("Android system emulator ver %s\n", VERSION);
233
234         snprintf(exec_dir, sizeof(exec_dir), "%s", dirname(argv[0]));
235
236         fd = socket(PF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
237         if (fd < 0) {
238                 perror("Failed to create system socket");
239                 return EXIT_FAILURE;
240         }
241
242         memset(&addr, 0, sizeof(addr));
243         addr.sun_family = AF_UNIX;
244         memcpy(addr.sun_path, SYSTEM_SOCKET_PATH, sizeof(SYSTEM_SOCKET_PATH));
245
246         if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
247                 perror("Failed to bind system socket");
248                 close(fd);
249                 return EXIT_FAILURE;
250         }
251
252         mainloop_add_fd(fd, EPOLLIN, system_socket_callback, NULL, NULL);
253
254         /* Make sure bluetoothd creates files with proper permissions */
255         umask(0177);
256
257         return mainloop_run();
258 }