|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: RtcBasePlugin |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "logger.h" |
|
20 #include "javacommonutils.h" |
|
21 |
|
22 #include "commsendpoint.h" |
|
23 #include "commsclientendpoint.h" |
|
24 #include "commsmessage.h" |
|
25 |
|
26 #include "rtcbaseplugin.h" |
|
27 #include "rtcmessages.h" |
|
28 #include "coremessages.h" |
|
29 |
|
30 #include "coreinterface.h" |
|
31 #include "timerserverinterface.h" |
|
32 #include "pmcinterface.h" |
|
33 |
|
34 namespace java |
|
35 { |
|
36 namespace captain |
|
37 { |
|
38 |
|
39 const int EXIT_TIMER_TIMEOUT = 5; |
|
40 const int LAUNCH_TIMER_TIMEOUT = 5; |
|
41 const int LAUNCH_TIMER_TIMEOUT_PREWARM = 60; |
|
42 |
|
43 RtcBasePlugin::RtcBasePlugin(const Uid& aUID, |
|
44 CoreInterface* aCore) |
|
45 :mUID(aUID), |
|
46 mCore(aCore), |
|
47 mState(APPLICATION_STATE_IDLE_C), |
|
48 mRuntimeAddress(0), |
|
49 mPid(-1), |
|
50 mTimerId(0), |
|
51 mPendingOperation(PENDING_OPERATION_NONE_C) |
|
52 { |
|
53 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
54 } |
|
55 |
|
56 RtcBasePlugin::~RtcBasePlugin() |
|
57 { |
|
58 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
59 |
|
60 runtime_init(); |
|
61 |
|
62 mCore = 0; |
|
63 } |
|
64 // Already routed on upper level using pid |
|
65 void RtcBasePlugin::pmcTerminated(const int& /*aPid*/, const int& /*exitCode*/) |
|
66 { |
|
67 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
68 |
|
69 mPid = -1; |
|
70 mRuntimeAddress = 0; |
|
71 |
|
72 switchState(APPLICATION_STATE_IDLE_C); |
|
73 } |
|
74 |
|
75 // TimerServerEventsInterface methods |
|
76 void RtcBasePlugin::timerTimeout(const int& aTimerId) |
|
77 { |
|
78 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
79 |
|
80 LOG1WSTR(EJavaCaptain, EError, "RtcBasePlugin::timerTimeout(%s)", mUID.toString()); |
|
81 LOG1(EJavaCaptain, EInfo, "runtime in state: %s", E2S_state(mState)); |
|
82 |
|
83 if (aTimerId == mTimerId) |
|
84 { |
|
85 mTimerId = 0; |
|
86 runtime_init(); |
|
87 } |
|
88 else |
|
89 { |
|
90 ELOG2(EJavaCaptain, "Wrong timerId! ok:%d FAIL:%d", mTimerId, aTimerId); |
|
91 } |
|
92 } |
|
93 |
|
94 bool RtcBasePlugin::launch(const rtcLaunchInfo& aLaunchInfo) |
|
95 { |
|
96 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
97 LOG1WSTR(EJavaCaptain, EInfoHeavyLoad, "RtcBasePlugin::launch(%s)", mUID.toString()); |
|
98 if (mUID == PREWARM_UID) |
|
99 { |
|
100 mUID = aLaunchInfo.mUID; |
|
101 } |
|
102 else if (mUID != aLaunchInfo.mUID) |
|
103 { |
|
104 ELOG(EJavaCaptain, "launch() called for a wrong instance"); |
|
105 return false; // not launched |
|
106 } |
|
107 |
|
108 mRuntimeArguments = aLaunchInfo.mRuntimeArguments; |
|
109 mApplicationArguments = aLaunchInfo.mApplicationArguments; |
|
110 |
|
111 bool launchSuccess = false; |
|
112 |
|
113 switch (mState) |
|
114 { |
|
115 case APPLICATION_STATE_IDLE_C: |
|
116 if (runtime_launch(aLaunchInfo.mLaunchType)) |
|
117 { |
|
118 launchSuccess = true; |
|
119 switchState(APPLICATION_STATE_LAUNCHED_C); |
|
120 } |
|
121 break; |
|
122 |
|
123 case APPLICATION_STATE_LAUNCHED_C: |
|
124 case APPLICATION_STATE_EXITING_C: |
|
125 launchSuccess = true; |
|
126 setPendingLaunch(aLaunchInfo.mLaunchType); |
|
127 break; // Just be happy |
|
128 |
|
129 case APPLICATION_STATE_RUNNING_C: |
|
130 launchSuccess = true; |
|
131 if (!runtime_relaunch(aLaunchInfo.mLaunchType)) // if fails |
|
132 { |
|
133 runtime_init(); // ???? |
|
134 // Launch a new instance |
|
135 if (runtime_launch(aLaunchInfo.mLaunchType)) |
|
136 { |
|
137 switchState(APPLICATION_STATE_LAUNCHED_C); |
|
138 } |
|
139 else |
|
140 { |
|
141 ELOG(EJavaCaptain, "Application launch failed!"); |
|
142 runtime_init(); |
|
143 switchState(APPLICATION_STATE_IDLE_C); |
|
144 launchSuccess = false; |
|
145 } |
|
146 } |
|
147 break; |
|
148 |
|
149 default: |
|
150 ELOG1(EJavaCaptain, "Invalid state -> %s", E2S_state(mState)); |
|
151 break; |
|
152 } |
|
153 |
|
154 return launchSuccess; |
|
155 } |
|
156 |
|
157 bool RtcBasePlugin::terminate(const rtcTerminateInfo& aTerminateInfo) |
|
158 { |
|
159 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
160 LOG1WSTR(EJavaCaptain, EInfoHeavyLoad, "terminate(%s)", mUID.toString()); |
|
161 |
|
162 if (mUID != aTerminateInfo.mUID) |
|
163 { |
|
164 ELOG(EJavaCaptain, "terminate() called for a wrong instance"); |
|
165 return true; // already terminated |
|
166 } |
|
167 |
|
168 bool isAlreadyTerminated = false; |
|
169 |
|
170 switch (mState) |
|
171 { |
|
172 case APPLICATION_STATE_IDLE_C: |
|
173 isAlreadyTerminated = true; |
|
174 break; |
|
175 |
|
176 case APPLICATION_STATE_LAUNCHED_C: |
|
177 setPendingTerminate(); |
|
178 break; |
|
179 |
|
180 case APPLICATION_STATE_RUNNING_C: |
|
181 if (runtime_terminate()) // terminate requested |
|
182 { |
|
183 switchState(APPLICATION_STATE_EXITING_C); |
|
184 } |
|
185 else // request failed, application probably already dead/zombie |
|
186 { |
|
187 runtime_init(); |
|
188 switchState(APPLICATION_STATE_IDLE_C); |
|
189 isAlreadyTerminated = true; |
|
190 } |
|
191 break; |
|
192 |
|
193 case APPLICATION_STATE_EXITING_C: |
|
194 break; |
|
195 |
|
196 default: |
|
197 ELOG1(EJavaCaptain, "Illegal state %d", mState); |
|
198 break; |
|
199 } |
|
200 |
|
201 return isAlreadyTerminated; |
|
202 } |
|
203 |
|
204 void RtcBasePlugin::switchState(const ApplicationState& newState) |
|
205 { |
|
206 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
207 LOG1WSTR(EJavaCaptain, EInfo, "switchState() and mUID is %s", mUID.toString()); |
|
208 LOG2(EJavaCaptain, EInfo, "switchState %s -> %s", E2S_state(mState), E2S_state(newState)); |
|
209 |
|
210 mState = newState; |
|
211 |
|
212 switch (newState) |
|
213 { |
|
214 case APPLICATION_STATE_IDLE_C: |
|
215 stopTimer(); |
|
216 if (mPid > 0 && mCore) |
|
217 { |
|
218 mCore->getPmc()->kill(mPid); |
|
219 } |
|
220 handlePendingOperations(); |
|
221 break; |
|
222 |
|
223 case APPLICATION_STATE_LAUNCHED_C: |
|
224 if (mUID == PREWARM_UID) |
|
225 { |
|
226 startTimer(LAUNCH_TIMER_TIMEOUT_PREWARM); |
|
227 } |
|
228 else |
|
229 { |
|
230 startTimer(LAUNCH_TIMER_TIMEOUT); |
|
231 } |
|
232 break; |
|
233 |
|
234 case APPLICATION_STATE_RUNNING_C: |
|
235 stopTimer(); |
|
236 handlePendingOperations(); |
|
237 break; |
|
238 |
|
239 case APPLICATION_STATE_EXITING_C: |
|
240 startTimer(EXIT_TIMER_TIMEOUT); |
|
241 break; |
|
242 |
|
243 default: |
|
244 ELOG1(EJavaCaptain, "Invalid new state requested %s", E2S_state(newState)); |
|
245 break; |
|
246 } |
|
247 } |
|
248 |
|
249 void RtcBasePlugin::runningInd(const int& aRuntimeAddress, const int& /*aStatus*/) |
|
250 { |
|
251 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
252 |
|
253 // Assumes that sender address is always latest and valid. |
|
254 mRuntimeAddress = aRuntimeAddress; |
|
255 |
|
256 switch (mState) |
|
257 { |
|
258 // Only handled once after launch othervise igoned |
|
259 case APPLICATION_STATE_LAUNCHED_C: |
|
260 switchState(APPLICATION_STATE_RUNNING_C); |
|
261 break; |
|
262 |
|
263 // Waking up a little bit too late, give another chance to do the right thing |
|
264 case APPLICATION_STATE_EXITING_C: |
|
265 runtime_terminate(); |
|
266 startTimer(EXIT_TIMER_TIMEOUT); |
|
267 break; |
|
268 |
|
269 default: |
|
270 break; |
|
271 } |
|
272 } |
|
273 |
|
274 void RtcBasePlugin::terminatedInd(const int& /*aStatus*/) |
|
275 { |
|
276 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
277 |
|
278 // Only handled if not already in EXITING state, |
|
279 // othervise ignored and deemed as an extra terminated_ind |
|
280 if (mState != APPLICATION_STATE_EXITING_C) |
|
281 { |
|
282 switchState(APPLICATION_STATE_EXITING_C); |
|
283 } |
|
284 } |
|
285 |
|
286 void RtcBasePlugin::processMessage(CommsMessage& message) |
|
287 { |
|
288 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
289 |
|
290 switch (message.getMessageId()) |
|
291 { |
|
292 case CORE_MSG_ID_DO_THREAD_DUMP: |
|
293 LOG(EJavaCaptain, EInfo, "sending DO_THREAD_DUMP message to runtime"); |
|
294 sendMessageToRuntime(message.getModuleId(), message); |
|
295 break; |
|
296 |
|
297 case RTC_MSG_ID_GET_EXTRA_ARGUMENTS: |
|
298 if (message.getSender() == mRuntimeAddress && isRunning()) |
|
299 { |
|
300 CommsMessage reply; |
|
301 reply.replyTo(message); |
|
302 setGetExtraArgumentsAck(reply, mRuntimeArguments, mApplicationArguments); |
|
303 LOG2(EJavaCaptain, EInfo, "reply to get runtime attributes: mUid=%S mRuntimeArguments=%S", |
|
304 mUID.toString().c_str(), mRuntimeArguments.c_str()); |
|
305 sendMessageToRuntime(message.getModuleId(), reply); |
|
306 } |
|
307 break; |
|
308 |
|
309 default: |
|
310 ELOG1(EJavaCaptain, "Unknown message forwarded to rtcplugin %d", message.getMessageId()); |
|
311 break; |
|
312 } |
|
313 } |
|
314 |
|
315 int RtcBasePlugin::sendMessageToRuntime(const int& moduleId, CommsMessage& message) |
|
316 { |
|
317 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
318 |
|
319 message.setReceiver(mRuntimeAddress); |
|
320 message.setModuleId(moduleId); |
|
321 |
|
322 return mCore->getComms()->send(message); |
|
323 } |
|
324 |
|
325 bool RtcBasePlugin::isRunning() const |
|
326 { |
|
327 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
328 |
|
329 return mState == APPLICATION_STATE_RUNNING_C; |
|
330 } |
|
331 |
|
332 void RtcBasePlugin::runtime_init() |
|
333 { |
|
334 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
335 |
|
336 if (mPid > 0 && mCore) |
|
337 { |
|
338 LOG1(EJavaCaptain, EInfo, "Killing process with uid %S", |
|
339 mUID.toString().c_str()); |
|
340 mCore->getPmc()->kill(mPid); |
|
341 } |
|
342 } |
|
343 |
|
344 bool RtcBasePlugin::runtime_launch(const int& aLaunchType) |
|
345 { |
|
346 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
347 |
|
348 std::vector<std::string> params; |
|
349 mPid = mCore->getPmc()->launch(generateCommandLine(aLaunchType, params), 0); |
|
350 return mPid > 0; |
|
351 } |
|
352 |
|
353 bool RtcBasePlugin::runtime_relaunch(const int& aLaunchType) |
|
354 { |
|
355 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
356 |
|
357 int status = 0; |
|
358 CommsMessage msg; |
|
359 |
|
360 switch (aLaunchType) |
|
361 { |
|
362 case RTC_LAUNCH_TYPE_PUSH_C: |
|
363 setUpdatePushReqParams(msg, mUID); |
|
364 status = sendMessageToRuntime(PLUGIN_ID_RTC_PUSH_C, msg); |
|
365 LOG1(EJavaCaptain, EInfo, "sendUpdatePushMessageToRuntime() returns %d", status); |
|
366 break; |
|
367 |
|
368 case RTC_LAUNCH_TYPE_PREWARM_C: // do nothing |
|
369 break; |
|
370 |
|
371 default: |
|
372 setLaunchApplicationReqParams(msg, mUID, aLaunchType, |
|
373 RTC_LAUNCH_OPTIONS_NONE_C, RTC_LAUNCH_RUNTIME_MIDP_C, mApplicationArguments); |
|
374 status = sendMessageToRuntime(PLUGIN_ID_RTC_C, msg); |
|
375 LOG1(EJavaCaptain, EInfo, |
|
376 "RtcBasePlugin::runtime_relaunch: sendMessageToRuntime() returns %d", status); |
|
377 break; |
|
378 } |
|
379 |
|
380 return status == 0; |
|
381 } |
|
382 |
|
383 bool RtcBasePlugin::runtime_terminate() |
|
384 { |
|
385 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
386 |
|
387 CommsMessage terminateMsg; |
|
388 setTerminateApplicationReqParams(terminateMsg, mUID, 0); |
|
389 int status = sendMessageToRuntime(PLUGIN_ID_RTC_C, terminateMsg); |
|
390 LOG1(EJavaCaptain, EInfo, "sendMessageToRuntime() returns %d", status); |
|
391 return status == 0; |
|
392 } |
|
393 |
|
394 void RtcBasePlugin::startTimer(const int& aTimeout) |
|
395 { |
|
396 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
397 |
|
398 // Only cancel if already started |
|
399 if (0 != mTimerId) |
|
400 { |
|
401 mCore->getTimerServer()->timerCancel(mTimerId); |
|
402 mTimerId = 0; |
|
403 } |
|
404 mTimerId = mCore->getTimerServer()->timerCreateSeconds(aTimeout, this); |
|
405 } |
|
406 void RtcBasePlugin::stopTimer() |
|
407 { |
|
408 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
409 |
|
410 if (0 != mTimerId) |
|
411 { |
|
412 mCore->getTimerServer()->timerCancel(mTimerId); |
|
413 mTimerId = 0; |
|
414 } |
|
415 } |
|
416 |
|
417 void RtcBasePlugin::setPendingLaunch(const int& aType) |
|
418 { |
|
419 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
420 switch (aType) |
|
421 { |
|
422 case RTC_LAUNCH_TYPE_NORMAL_C: |
|
423 mPendingOperation = PENDING_OPERATION_LAUNCH_NORMAL_C; |
|
424 break; |
|
425 |
|
426 case RTC_LAUNCH_TYPE_PUSH_C: |
|
427 mPendingOperation = PENDING_OPERATION_LAUNCH_PUSH_C; |
|
428 break; |
|
429 |
|
430 case RTC_LAUNCH_TYPE_AUTO_INVOCATION_C: |
|
431 mPendingOperation = PENDING_OPERATION_LAUNCH_AUTO_INVOCATION_C; |
|
432 break; |
|
433 |
|
434 case RTC_LAUNCH_TYPE_BACKGROUND_C: |
|
435 mPendingOperation = PENDING_OPERATION_LAUNCH_BACKGROUND_C; |
|
436 break; |
|
437 |
|
438 case RTC_LAUNCH_TYPE_DEBUG_C: |
|
439 mPendingOperation = PENDING_OPERATION_LAUNCH_DEBUG_C; |
|
440 break; |
|
441 |
|
442 default: |
|
443 ELOG1(EJavaCaptain, "Unknown pending launch type! (%d)", aType); |
|
444 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
445 break; |
|
446 } |
|
447 } |
|
448 |
|
449 void RtcBasePlugin::setPendingTerminate() |
|
450 { |
|
451 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
452 mPendingOperation = PENDING_OPERATION_TERMINATE_C; |
|
453 } |
|
454 |
|
455 void RtcBasePlugin::handlePendingOperations() |
|
456 { |
|
457 JELOG4(EJavaCaptain, EInfoHeavyLoad); |
|
458 switch (mPendingOperation) |
|
459 { |
|
460 case PENDING_OPERATION_LAUNCH_NORMAL_C: |
|
461 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
462 launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_NORMAL_C)); |
|
463 break; |
|
464 case PENDING_OPERATION_LAUNCH_PUSH_C: |
|
465 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
466 launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_PUSH_C)); |
|
467 break; |
|
468 case PENDING_OPERATION_LAUNCH_AUTO_INVOCATION_C: |
|
469 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
470 launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_AUTO_INVOCATION_C)); |
|
471 break; |
|
472 case PENDING_OPERATION_LAUNCH_BACKGROUND_C: |
|
473 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
474 launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_BACKGROUND_C)); |
|
475 break; |
|
476 case PENDING_OPERATION_LAUNCH_DEBUG_C: |
|
477 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
478 launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_DEBUG_C)); |
|
479 break; |
|
480 case PENDING_OPERATION_TERMINATE_C: |
|
481 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
482 terminate(rtcTerminateInfo(mUID)); |
|
483 break; |
|
484 case PENDING_OPERATION_NONE_C: |
|
485 default: |
|
486 mPendingOperation = PENDING_OPERATION_NONE_C; |
|
487 break; |
|
488 } |
|
489 } |
|
490 |
|
491 } // namespace captain |
|
492 } // namespace java |
|
493 |