update source for tizen_2.1
[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 #define SKIN_SERVER_READY_TIME 3 // second
53 #define SKIN_SERVER_SLEEP_TIME 10 // milli second
54
55 #define OPT_SVR_PORT "svr.port"
56 #define OPT_UID "uid"
57 #define OPT_VM_PATH "vm.path"
58 #define OPT_NET_BASE_PORT "net.baseport"
59 #define OPT_MAX_TOUCHPOINT "max.touchpoint"
60
61 extern char tizen_target_path[];
62
63 static int skin_argc;
64 static char** skin_argv;
65
66 #ifdef CONFIG_WIN32
67 static char* JAVA_EXEFILE_PATH = NULL;
68 #endif
69
70 static void* run_skin_client(void* arg)
71 {
72     char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
73     char argv[JAVA_MAX_COMMAND_LENGTH] = { 0, };
74
75     INFO("run skin client\n");
76     int i;
77     for (i = 0; i < skin_argc; ++i) {
78         strncat(argv, skin_argv[i], strlen(skin_argv[i]));
79         strncat(argv, " ", 1);
80         INFO("[skin args %d] %s\n", i, skin_argv[i]);
81     }
82
83     int skin_server_port = get_skin_server_port();
84
85     //srand( time( NULL ) );
86     int uid = 0; //rand();
87     //INFO( "generated skin uid:%d\n", uid );
88
89     char* vm_path = tizen_target_path;
90     //INFO( "vm_path:%s\n", vm_path );
91     char buf_skin_server_port[16];
92     char buf_uid[16];
93     char buf_tizen_base_port[16];
94     sprintf(buf_skin_server_port, "%d", skin_server_port);
95     sprintf(buf_uid, "%d", uid);
96     sprintf(buf_tizen_base_port, "%d", get_emul_vm_base_port());
97
98 #ifdef CONFIG_WIN32
99     // find java path in 64bit windows
100     JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH);
101     memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH);
102     if (is_wow64()) {
103         INFO("This process is running under WOW64.\n");
104         if (!get_java_path(&JAVA_EXEFILE_PATH)) {
105              strcpy(JAVA_EXEFILE_PATH, "java");
106         }
107     } else {
108         strcpy(JAVA_EXEFILE_PATH, "java");
109     }
110
111     char* bin_dir = get_bin_path();
112     int bin_len = strlen(bin_dir);
113     char bin_dir_win[bin_len];
114     strcpy(bin_dir_win, bin_dir);
115     bin_dir_win[strlen(bin_dir_win) -1] = '\0';
116 #else
117     char* bin_dir = get_bin_path();
118 #endif
119     INFO("bin directory : %s\n", bin_dir);
120
121     int maxtouchpoint = get_emul_max_touch_point();
122     int len_maxtouchpoint;
123     if (maxtouchpoint > 9) {
124         len_maxtouchpoint = 2;
125     } else {
126         len_maxtouchpoint = 1;
127     }
128
129     int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) +
130 #ifdef CONFIG_WIN32
131             strlen((char*)bin_dir_win) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
132 #else
133             strlen(bin_dir) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
134 #endif
135         strlen(OPT_SVR_PORT) + strlen(buf_skin_server_port) + strlen(OPT_UID) + strlen(buf_uid) +
136         strlen(OPT_VM_PATH) + strlen(vm_path) + strlen(OPT_NET_BASE_PORT) + strlen(buf_tizen_base_port) +
137         strlen(OPT_MAX_TOUCHPOINT) + len_maxtouchpoint + strlen(argv) + 46;
138     if (len > JAVA_MAX_COMMAND_LENGTH) {
139         INFO("swt command length is too long! (%d)\n", len);
140         len = JAVA_MAX_COMMAND_LENGTH;
141     }
142
143     snprintf(cmd, len, "%s %s %s=\"%s\" \"%s%s\" %s=\"%d\" %s=\"%d\" %s=\"%s\" %s=\"%d\" %s=%d %s",
144         JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH,
145 #ifdef CONFIG_WIN32
146         bin_dir_win, bin_dir, JAR_SKINFILE,
147 #else
148         bin_dir, bin_dir, JAR_SKINFILE,
149 #endif
150         OPT_SVR_PORT, skin_server_port,
151         OPT_UID, uid,
152         OPT_VM_PATH, vm_path,
153         OPT_NET_BASE_PORT, get_emul_vm_base_port(),
154         OPT_MAX_TOUCHPOINT, maxtouchpoint,
155         argv);
156
157     INFO("command for swt : %s\n", cmd);
158
159 #ifdef CONFIG_WIN32
160     // for 64bit windows
161     free(JAVA_EXEFILE_PATH);
162     JAVA_EXEFILE_PATH = NULL;
163
164     //WinExec( cmd, SW_SHOW );
165     {
166         STARTUPINFO sti = { 0 };
167         PROCESS_INFORMATION pi = { 0 };
168         if (!CreateProcess(NULL,
169                           cmd,
170                           NULL,
171                           NULL,
172                           FALSE,
173                           NORMAL_PRIORITY_CLASS,
174                           NULL,
175                           NULL,
176                           &sti,
177                           &pi))
178         {
179             ERR("Unable to generate process! error %u\n", GetLastError());
180             maru_register_exit_msg(MARU_EXIT_UNKNOWN,
181                 "CreateProcess function failed. Unable to generate process.");
182             exit(1);
183         }
184
185         INFO("wait for single object..\n");
186         DWORD dwRet = WaitForSingleObject(
187                           pi.hProcess, // process handle
188                           INFINITE);
189
190         switch(dwRet) {
191         case WAIT_OBJECT_0:
192             INFO("the child thread state was signaled!\n");
193             break;
194         case WAIT_TIMEOUT:
195             INFO("time-out interval elapsed,\
196                 and the child thread's state is nonsignaled.\n");
197             break;
198         case WAIT_FAILED:
199             ERR("WaitForSingleObject() failed, error %u\n", GetLastError());
200             break;
201         }
202
203         //retrieves the termination status of the specified process
204         if (GetExitCodeProcess(pi.hProcess, &dwRet) != 0) {
205             ERR("failed to GetExitCodeProcess, error %u\n", GetLastError());
206         }
207         INFO("child return value : %d\n", dwRet);
208
209         if (dwRet != 0) {
210             /* child process is terminated with some problem.
211             So qemu process will terminate, too. immediately. */
212             shutdown_qemu_gracefully();
213         }
214
215         if (CloseHandle(pi.hProcess) != 0) {
216             INFO("child thread handle was closed successfully!\n");
217         } else {
218             ERR("failed to close child thread handle, error %u\n", GetLastError());
219         }
220     }
221
222 #else //ifndef CONFIG_WIN32
223     int ret = system(cmd);
224
225     if (ret == 127) {
226         INFO("can't execute /bin/sh!\n");
227     } else if(ret == -1) {
228         INFO("fork error!\n");
229     } else {
230         ret = WEXITSTATUS(ret);
231         //The high-order 8 bits are the exit code from exit().
232         //The low-order 8 bits are zero if the process exited normally.
233         INFO("child return value : %d\n", ret);
234
235         if (ret != 0) {
236             /* child process is terminated with some problem.
237             So qemu process will terminate, too. immediately. */
238             shutdown_qemu_gracefully();
239         }
240     }
241
242 #endif
243
244     return NULL;
245 }
246
247 int start_skin_client(int argc, char* argv[])
248 {
249     int count = 0;
250     int skin_server_ready = 0;
251
252     while(1) {
253
254         if (100 * SKIN_SERVER_READY_TIME < count) {
255             break;
256         }
257
258         if (is_ready_skin_server()) {
259             skin_server_ready = 1;
260             break;
261         } else {
262             count++;
263             INFO("sleep for ready. count:%d\n", count);
264
265 #ifdef CONFIG_WIN32
266             Sleep(SKIN_SERVER_SLEEP_TIME);
267 #else
268             usleep(1000 * SKIN_SERVER_SLEEP_TIME);
269 #endif
270         }
271
272     }
273
274     if (!skin_server_ready) {
275         ERR("skin_server is not ready.\n");
276         return -1;
277     }
278
279     skin_argc = argc;
280     skin_argv = argv;
281
282     pthread_t thread_id;
283
284     if (0 != pthread_create(&thread_id, NULL, run_skin_client, NULL)) {
285         ERR( "fail to create skin_client pthread.\n" );
286         return -1;
287     }
288
289     return 1;
290 }
291
292 int start_simple_client(char* msg)
293 {
294     int ret = 0;
295     char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, };
296
297     INFO("run simple client\n");
298
299 #ifdef CONFIG_WIN32
300     // find java path in 64bit windows
301     JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH);
302     memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH);
303     if (is_wow64()) {
304         INFO("This process is running under WOW64.\n");
305         if (!get_java_path(&JAVA_EXEFILE_PATH)) {
306              strcpy(JAVA_EXEFILE_PATH, "java");
307         }
308     } else {
309         strcpy(JAVA_EXEFILE_PATH, "java");
310     }
311     char* bin_dir = get_bin_path();
312     int bin_dir_len = strlen(bin_dir);
313     char bin_dir_win[bin_dir_len];
314     strcpy(bin_dir_win, bin_dir);
315     bin_dir_win[strlen(bin_dir_win) -1] = '\0';
316 #else
317     char* bin_dir = get_bin_path();
318 #endif
319     INFO("bin directory : %s\n", bin_dir);
320
321
322     int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + strlen(JAVA_LIBRARY_PATH) +
323 #ifdef CONFIG_WIN32
324             strlen((char*)bin_dir_win) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
325 #else
326             strlen(bin_dir) + strlen(bin_dir) + strlen(JAR_SKINFILE) +
327 #endif
328             strlen(bin_dir) + strlen(JAVA_SIMPLEMODE_OPTION) + strlen(msg) + 11;
329     if (len > JAVA_MAX_COMMAND_LENGTH) {
330         len = JAVA_MAX_COMMAND_LENGTH;
331     }
332     snprintf(cmd, len, "%s %s %s=\"%s\" %s%s %s=\"%s\"",
333 #ifdef CONFIG_WIN32
334     JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH, bin_dir_win,
335 #else
336     JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAVA_LIBRARY_PATH, bin_dir,
337 #endif
338     bin_dir, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, msg);
339     INFO("command for swt : %s\n", cmd);
340
341 #ifdef CONFIG_WIN32
342     // for 64bit windows
343     free(JAVA_EXEFILE_PATH);
344     JAVA_EXEFILE_PATH=0;
345
346     ret = WinExec(cmd, SW_SHOW);
347 #else
348     ret = system(cmd);
349 #endif
350
351     INFO("child return value : %d\n", ret);
352
353     return 1;
354 }
355
356 #ifdef CONFIG_WIN32
357 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
358 LPFN_ISWOW64PROCESS fnIsWow64Process;
359
360 int is_wow64(void)
361 {
362     int result = 0;
363
364     //IsWow64Process is not available on all supported versions of Windows.
365     //Use GetModuleHandle to get a handle to the DLL that contains the function
366     //and GetProcAddress to get a pointer to the function if available.
367
368     fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
369         GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
370
371     if(NULL != fnIsWow64Process)
372     {
373         if (!fnIsWow64Process(GetCurrentProcess(),&result))
374         {
375             //handle error
376             INFO("Can not find 'IsWow64Process'\n");
377         }
378     }
379     return result;
380 }
381
382 int get_java_path(char** java_path)
383 {
384     HKEY hKeyNew;
385     HKEY hKey;
386     //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0};
387     char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0};
388     char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0};
389     char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0};
390     int index;
391     DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH;
392     DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH;
393
394     RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment", 0,
395                                      KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY, &hKey);
396     RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax, NULL, NULL, NULL, NULL);
397     strcpy(strChoosenName, strSubKeyName);
398
399     index = 1;
400     while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, (LPSTR)strSubKeyName, &dwSubKeyNameMax,
401             NULL, NULL, NULL, NULL)) {
402         if (strcmp(strChoosenName, strSubKeyName) < 0) {
403             strcpy(strChoosenName, strSubKeyName);
404         }
405         index++;
406     }
407
408     RegOpenKeyEx(hKey, strChoosenName, 0, KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, &hKeyNew);
409     RegQueryValueEx(hKeyNew, "JavaHome", NULL, NULL, (LPBYTE)strJavaHome, &dwBufLen);
410     RegCloseKey(hKey);
411     if (strJavaHome[0] != '\0') {
412         sprintf(*java_path, "\"%s\\bin\\java\"", strJavaHome);
413         //strcpy(*java_path, strJavaHome);
414         //strcat(*java_path, "\\bin\\java");
415     } else {
416         return 0;
417     }
418     return 1;
419 }
420 #endif