Tizen 2.1 base
[sdk/emulator/qemu.git] / tizen / src / skin / maruskin_client.c
1 /*
2  * communicate with java skin process
3  *
4  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * GiWoong Kim <giwoong.kim@samsung.com>
8  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
9  * HyunJun Son
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30
31 #include "maru_common.h"
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <pthread.h>
37 #include "maruskin_client.h"
38 #include "maruskin_server.h"
39 #include "emulator.h"
40 #include "sdb.h"
41 #include "debug_ch.h"
42 #include "emul_state.h"
43 #include "maruskin_operation.h"
44
45 #ifdef CONFIG_WIN32
46 #include "maru_err_table.h"
47 #include <windows.h>
48 #endif
49
50 MULTI_DEBUG_CHANNEL(qemu, skin_client);
51
52
53 #define SKIN_SERVER_READY_TIME 3 // second
54 #define SKIN_SERVER_SLEEP_TIME 10 // milli second
55
56 #define OPT_SVR_PORT "svr.port"
57 #define OPT_UID "uid"
58 #define OPT_VM_PATH "vm.path"
59 #define OPT_NET_BASE_PORT "net.baseport"
60 #define OPT_MAX_TOUCHPOINT "max.touchpoint"
61
62 extern char tizen_target_path[];
63
64 static int skin_argc;
65 static char** skin_argv;
66
67 static void* run_skin_client(void* arg)
68 {
69     char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
70     char argv[JAVA_MAX_COMMAND_LENGTH] = { 0, };
71
72     INFO("run skin client\n");
73     int i;
74     for (i = 0; i < skin_argc; ++i) {
75         strncat(argv, skin_argv[i], strlen(skin_argv[i]));
76         strncat(argv, " ", 1);
77         INFO("[skin args %d] %s\n", i, skin_argv[i]);
78     }
79
80     int skin_server_port = get_skin_server_port();
81
82     //srand( time( NULL ) );
83     int uid = 0; //rand();
84     //INFO( "generated skin uid:%d\n", uid );
85
86     char* vm_path = tizen_target_path;
87     //INFO( "vm_path:%s\n", vm_path );
88     char buf_skin_server_port[16];
89     char buf_uid[16];
90     char buf_tizen_base_port[16];
91     sprintf(buf_skin_server_port, "%d", skin_server_port);
92     sprintf(buf_uid, "%d", uid);
93     sprintf(buf_tizen_base_port, "%d", tizen_base_port);
94
95 #ifdef CONFIG_WIN32
96     // find java path in 64bit windows
97     JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH);
98     memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH);
99     if (is_wow64()) {
100         INFO("This process is running under WOW64.\n");
101         if (!get_java_path(&JAVA_EXEFILE_PATH)) {
102              strcpy(JAVA_EXEFILE_PATH, "java");
103         }
104     } else {
105         strcpy(JAVA_EXEFILE_PATH, "java");
106     }
107
108     char* bin_dir = get_bin_path();
109     int bin_len = strlen(bin_dir);
110     char bin_dir_win[bin_len];
111     strcpy(bin_dir_win, bin_dir);
112     bin_dir_win[strlen(bin_dir_win) -1] = '\0';
113 #else
114     char* bin_dir = get_bin_path();
115 #endif
116     INFO("bin directory : %s\n", bin_dir);
117     int maxtouchpoint = get_emul_max_touch_point();
118     int len_maxtouchpoint;
119     if(maxtouchpoint > 9) {
120         len_maxtouchpoint = 2;
121     }else {
122         len_maxtouchpoint = 1;
123     }
124
125     int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) +
126 #ifdef CONFIG_WIN32
127             strlen((char*)bin_dir_win) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
128 #else
129             strlen(bin_dir) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
130 #endif
131         strlen(OPT_SVR_PORT) + strlen(buf_skin_server_port) + strlen(OPT_UID) + strlen(buf_uid) +
132         strlen(OPT_VM_PATH) + strlen(vm_path) + strlen(OPT_NET_BASE_PORT) + strlen(buf_tizen_base_port) +
133         strlen(OPT_MAX_TOUCHPOINT) + len_maxtouchpoint + strlen(argv) + 46;
134     if (len > JAVA_MAX_COMMAND_LENGTH) {
135         INFO("swt command length is too long! (%d)\n", len);
136         len = JAVA_MAX_COMMAND_LENGTH;
137     }
138
139     snprintf(cmd, len, "%s %s %s=\"%s\" \"%s%s\" %s=\"%d\" %s=\"%d\" %s=\"%s\" %s=\"%d\" %s=%d %s",
140         JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH,
141 #ifdef CONFIG_WIN32
142         bin_dir_win, bin_dir, JAR_SKINFILE,
143 #else
144         bin_dir, bin_dir, JAR_SKINFILE,
145 #endif
146         OPT_SVR_PORT, skin_server_port,
147         OPT_UID, uid,
148         OPT_VM_PATH, vm_path,
149         OPT_NET_BASE_PORT, tizen_base_port,
150         OPT_MAX_TOUCHPOINT, maxtouchpoint,
151         argv );
152
153     INFO("command for swt : %s\n", cmd);
154
155 #ifdef CONFIG_WIN32
156     // for 64bit windows
157     free(JAVA_EXEFILE_PATH);
158     JAVA_EXEFILE_PATH=0;
159
160     //WinExec( cmd, SW_SHOW );
161     {
162         STARTUPINFO sti = { 0 };
163         PROCESS_INFORMATION pi = { 0 };
164         if (!CreateProcess(NULL,
165                           cmd,
166                           NULL,
167                           NULL,
168                           FALSE,
169                           NORMAL_PRIORITY_CLASS,
170                           NULL,
171                           NULL,
172                           &sti,
173                           &pi))
174         {
175             ERR("Unable to generate process! error %u\n", GetLastError());
176             maru_register_exit_msg(MARU_EXIT_UNKNOWN,
177                 "CreateProcess function failed. Unable to generate process.");
178             exit(1);
179         }
180
181         INFO("wait for single object..\n");
182         DWORD dwRet = WaitForSingleObject(
183                           pi.hProcess, // process handle
184                           INFINITE);
185
186         switch(dwRet) {
187         case WAIT_OBJECT_0:
188             INFO("the child thread state was signaled!\n");
189             break;
190         case WAIT_TIMEOUT:
191             INFO("time-out interval elapsed,\
192                 and the child thread's state is nonsignaled.\n");
193             break;
194         case WAIT_FAILED:
195             ERR("WaitForSingleObject() failed, error %u\n", GetLastError());
196             break;
197         }
198
199         //retrieves the termination status of the specified process
200         if (GetExitCodeProcess(pi.hProcess, &dwRet) != 0) {
201             ERR("failed to GetExitCodeProcess, error %u\n", GetLastError());
202         }
203         INFO("child return value : %d\n", dwRet);
204
205         if (dwRet != 0) {
206             /* child process is terminated with some problem.
207             So qemu process will terminate, too. immediately. */
208             shutdown_qemu_gracefully();
209         }
210
211         if (CloseHandle(pi.hProcess) != 0) {
212             INFO("child thread handle was closed successfully!\n");
213         } else {
214             ERR("failed to close child thread handle, error %u\n", GetLastError());
215         }
216     }
217
218 #else //ifndef CONFIG_WIN32
219     int ret = system(cmd);
220
221     if (ret == 127) {
222         INFO("can't execute /bin/sh!\n");
223     } else if(ret == -1) {
224         INFO("fork error!\n");
225     } else {
226         ret = WEXITSTATUS(ret);
227         //The high-order 8 bits are the exit code from exit().
228         //The low-order 8 bits are zero if the process exited normally.
229         INFO("child return value : %d\n", ret);
230
231         if (ret != 0) {
232             /* child process is terminated with some problem.
233             So qemu process will terminate, too. immediately. */
234             shutdown_qemu_gracefully();
235         }
236     }
237
238 #endif
239
240     return NULL;
241 }
242
243 int start_skin_client(int argc, char* argv[])
244 {
245     int count = 0;
246     int skin_server_ready = 0;
247
248     while(1) {
249
250         if (100 * SKIN_SERVER_READY_TIME < count) {
251             break;
252         }
253
254         if (is_ready_skin_server()) {
255             skin_server_ready = 1;
256             break;
257         } else {
258             count++;
259             INFO("sleep for ready. count:%d\n", count);
260 #ifdef CONFIG_WIN32
261         Sleep(SKIN_SERVER_SLEEP_TIME);
262 #else
263         usleep(1000 * SKIN_SERVER_SLEEP_TIME);
264 #endif
265         }
266
267     }
268
269     if (!skin_server_ready) {
270         ERR("skin_server is not ready.\n");
271         return -1;
272     }
273
274     skin_argc = argc;
275     skin_argv = argv;
276
277     pthread_t thread_id;
278
279     if (0 != pthread_create(&thread_id, NULL, run_skin_client, NULL)) {
280         ERR( "fail to create skin_client pthread.\n" );
281         return -1;
282     }
283
284     return 1;
285 }
286
287 int start_simple_client(char* msg)
288 {
289     int ret = 0;
290     char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
291
292     INFO("run simple client\n");
293
294 #ifdef CONFIG_WIN32
295     // find java path in 64bit windows
296     JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH);
297     memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH);
298     if (is_wow64()) {
299         INFO("This process is running under WOW64.\n");
300         if (!get_java_path(&JAVA_EXEFILE_PATH)) {
301              strcpy(JAVA_EXEFILE_PATH, "java");
302         }
303     } else {
304         strcpy(JAVA_EXEFILE_PATH, "java");
305     }
306     char* bin_dir = get_bin_path();
307     int bin_dir_len = strlen(bin_dir);
308     char bin_dir_win[bin_dir_len];
309     strcpy(bin_dir_win, bin_dir);
310     bin_dir_win[strlen(bin_dir_win) -1] = '\0';
311 #else
312     char* bin_dir = get_bin_path();
313 #endif
314     INFO("bin directory : %s\n", bin_dir);
315
316
317     int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + strlen(JAVA_LIBRARY_PATH) +
318 #ifdef CONFIG_WIN32
319             strlen((char*)bin_dir_win) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
320 #else
321             strlen(bin_dir) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
322 #endif
323             strlen(bin_dir) + strlen(JAVA_SIMPLEMODE_OPTION) + strlen(msg) + 11;
324     if (len > JAVA_MAX_COMMAND_LENGTH) {
325         len = JAVA_MAX_COMMAND_LENGTH;
326     }
327     snprintf(cmd, len, "%s %s %s=\"%s\" %s%s %s=\"%s\"",
328 #ifdef CONFIG_WIN32
329     JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH, bin_dir_win,
330 #else
331     JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH, bin_dir,
332 #endif
333     bin_dir, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, msg);
334     INFO("command for swt : %s\n", cmd);
335
336 #ifdef CONFIG_WIN32
337     // for 64bit windows
338     free(JAVA_EXEFILE_PATH);
339     JAVA_EXEFILE_PATH=0;
340
341     ret = WinExec(cmd, SW_SHOW);
342 #else
343     ret = system(cmd);
344 #endif
345
346     INFO("child return value : %d\n", ret);
347
348     return 1;
349 }
350
351 #ifdef CONFIG_WIN32
352 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
353 LPFN_ISWOW64PROCESS fnIsWow64Process;
354
355 int is_wow64(void)
356 {
357     int result = 0;
358
359     //IsWow64Process is not available on all supported versions of Windows.
360     //Use GetModuleHandle to get a handle to the DLL that contains the function
361     //and GetProcAddress to get a pointer to the function if available.
362
363     fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
364         GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
365
366     if(NULL != fnIsWow64Process)
367     {
368         if (!fnIsWow64Process(GetCurrentProcess(),&result))
369         {
370             //handle error
371             INFO("Can not find 'IsWow64Process'\n");
372         }
373     }
374     return result;
375 }
376
377 int get_java_path(char** java_path)
378 {
379     HKEY hKeyNew;
380     HKEY hKey;
381     //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0};
382     char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0};
383     char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0};
384     char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0};
385     int index;
386     DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH;
387     DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH;
388
389     RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment", 0,
390                                      KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY, &hKey);
391     RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax, NULL, NULL, NULL, NULL);
392     strcpy(strChoosenName, strSubKeyName);
393
394     index = 1;
395     while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, (LPSTR)strSubKeyName, &dwSubKeyNameMax,
396             NULL, NULL, NULL, NULL)) {
397         if (strcmp(strChoosenName, strSubKeyName) < 0) {
398             strcpy(strChoosenName, strSubKeyName);
399         }
400         index++;
401     }
402
403     RegOpenKeyEx(hKey, strChoosenName, 0, KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, &hKeyNew);
404     RegQueryValueEx(hKeyNew, "JavaHome", NULL, NULL, (LPBYTE)strJavaHome, &dwBufLen);
405     RegCloseKey(hKey);
406     if (strJavaHome[0] != '\0') {
407         sprintf(*java_path, "\"%s\\bin\\java\"", strJavaHome);
408         //strcpy(*java_path, strJavaHome);
409         //strcat(*java_path, "\\bin\\java");
410     } else {
411         return 0;
412     }
413     return 1;
414 }
415 #endif