javamanager/javacaptain/src/rtcbaseplugin.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javamanager/javacaptain/src/rtcbaseplugin.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,493 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  RtcBasePlugin
+*
+*/
+
+
+#include "logger.h"
+#include "javacommonutils.h"
+
+#include "commsendpoint.h"
+#include "commsclientendpoint.h"
+#include "commsmessage.h"
+
+#include "rtcbaseplugin.h"
+#include "rtcmessages.h"
+#include "coremessages.h"
+
+#include "coreinterface.h"
+#include "timerserverinterface.h"
+#include "pmcinterface.h"
+
+namespace java
+{
+namespace captain
+{
+
+const int EXIT_TIMER_TIMEOUT    = 5;
+const int LAUNCH_TIMER_TIMEOUT  = 5;
+const int LAUNCH_TIMER_TIMEOUT_PREWARM  = 60;
+
+RtcBasePlugin::RtcBasePlugin(const Uid& aUID,
+                             CoreInterface* aCore)
+        :mUID(aUID),
+        mCore(aCore),
+        mState(APPLICATION_STATE_IDLE_C),
+        mRuntimeAddress(0),
+        mPid(-1),
+        mTimerId(0),
+        mPendingOperation(PENDING_OPERATION_NONE_C)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+}
+
+RtcBasePlugin::~RtcBasePlugin()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    runtime_init();
+
+    mCore = 0;
+}
+// Already routed on upper level using pid
+void RtcBasePlugin::pmcTerminated(const int& /*aPid*/, const int& /*exitCode*/)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    mPid = -1;
+    mRuntimeAddress = 0;
+
+    switchState(APPLICATION_STATE_IDLE_C);
+}
+
+// TimerServerEventsInterface methods
+void RtcBasePlugin::timerTimeout(const int& aTimerId)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    LOG1WSTR(EJavaCaptain, EError, "RtcBasePlugin::timerTimeout(%s)", mUID.toString());
+    LOG1(EJavaCaptain, EInfo, "runtime in state: %s", E2S_state(mState));
+
+    if (aTimerId == mTimerId)
+    {
+        mTimerId = 0;
+        runtime_init();
+    }
+    else
+    {
+        ELOG2(EJavaCaptain, "Wrong timerId! ok:%d FAIL:%d", mTimerId, aTimerId);
+    }
+}
+
+bool RtcBasePlugin::launch(const rtcLaunchInfo& aLaunchInfo)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    LOG1WSTR(EJavaCaptain, EInfoHeavyLoad, "RtcBasePlugin::launch(%s)", mUID.toString());
+    if (mUID == PREWARM_UID)
+    {
+        mUID = aLaunchInfo.mUID;
+    }
+    else if (mUID != aLaunchInfo.mUID)
+    {
+        ELOG(EJavaCaptain, "launch() called for a wrong instance");
+        return false; // not launched
+    }
+
+    mRuntimeArguments = aLaunchInfo.mRuntimeArguments;
+    mApplicationArguments = aLaunchInfo.mApplicationArguments;
+
+    bool launchSuccess = false;
+
+    switch (mState)
+    {
+    case APPLICATION_STATE_IDLE_C:
+        if (runtime_launch(aLaunchInfo.mLaunchType))
+        {
+            launchSuccess = true;
+            switchState(APPLICATION_STATE_LAUNCHED_C);
+        }
+        break;
+
+    case APPLICATION_STATE_LAUNCHED_C:
+    case APPLICATION_STATE_EXITING_C:
+        launchSuccess = true;
+        setPendingLaunch(aLaunchInfo.mLaunchType);
+        break; // Just be happy
+
+    case APPLICATION_STATE_RUNNING_C:
+        launchSuccess = true;
+        if (!runtime_relaunch(aLaunchInfo.mLaunchType))   // if fails
+        {
+            runtime_init(); // ????
+            // Launch a new instance
+            if (runtime_launch(aLaunchInfo.mLaunchType))
+            {
+                switchState(APPLICATION_STATE_LAUNCHED_C);
+            }
+            else
+            {
+                ELOG(EJavaCaptain, "Application launch failed!");
+                runtime_init();
+                switchState(APPLICATION_STATE_IDLE_C);
+                launchSuccess = false;
+            }
+        }
+        break;
+
+    default:
+        ELOG1(EJavaCaptain, "Invalid state -> %s", E2S_state(mState));
+        break;
+    }
+
+    return launchSuccess;
+}
+
+bool RtcBasePlugin::terminate(const rtcTerminateInfo& aTerminateInfo)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    LOG1WSTR(EJavaCaptain, EInfoHeavyLoad, "terminate(%s)", mUID.toString());
+
+    if (mUID != aTerminateInfo.mUID)
+    {
+        ELOG(EJavaCaptain, "terminate() called for a wrong instance");
+        return true; // already terminated
+    }
+
+    bool isAlreadyTerminated = false;
+
+    switch (mState)
+    {
+    case APPLICATION_STATE_IDLE_C:
+        isAlreadyTerminated = true;
+        break;
+
+    case APPLICATION_STATE_LAUNCHED_C:
+        setPendingTerminate();
+        break;
+
+    case APPLICATION_STATE_RUNNING_C:
+        if (runtime_terminate())   // terminate requested
+        {
+            switchState(APPLICATION_STATE_EXITING_C);
+        }
+        else // request failed, application probably already dead/zombie
+        {
+            runtime_init();
+            switchState(APPLICATION_STATE_IDLE_C);
+            isAlreadyTerminated = true;
+        }
+        break;
+
+    case APPLICATION_STATE_EXITING_C:
+        break;
+
+    default:
+        ELOG1(EJavaCaptain, "Illegal state %d", mState);
+        break;
+    }
+
+    return isAlreadyTerminated;
+}
+
+void RtcBasePlugin::switchState(const ApplicationState& newState)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    LOG1WSTR(EJavaCaptain, EInfo, "switchState() and mUID is %s", mUID.toString());
+    LOG2(EJavaCaptain, EInfo, "switchState %s -> %s", E2S_state(mState), E2S_state(newState));
+
+    mState = newState;
+
+    switch (newState)
+    {
+    case  APPLICATION_STATE_IDLE_C:
+        stopTimer();
+        if (mPid > 0 && mCore)
+        {
+            mCore->getPmc()->kill(mPid);
+        }
+        handlePendingOperations();
+        break;
+
+    case APPLICATION_STATE_LAUNCHED_C:
+        if (mUID == PREWARM_UID)
+        {
+            startTimer(LAUNCH_TIMER_TIMEOUT_PREWARM);
+        }
+        else
+        {
+            startTimer(LAUNCH_TIMER_TIMEOUT);
+        }
+        break;
+
+    case APPLICATION_STATE_RUNNING_C:
+        stopTimer();
+        handlePendingOperations();
+        break;
+
+    case APPLICATION_STATE_EXITING_C:
+        startTimer(EXIT_TIMER_TIMEOUT);
+        break;
+
+    default:
+        ELOG1(EJavaCaptain, "Invalid new state requested %s", E2S_state(newState));
+        break;
+    }
+}
+
+void RtcBasePlugin::runningInd(const int& aRuntimeAddress, const int& /*aStatus*/)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    // Assumes that sender address is always latest and valid.
+    mRuntimeAddress = aRuntimeAddress;
+
+    switch (mState)
+    {
+        // Only handled once after launch othervise igoned
+    case APPLICATION_STATE_LAUNCHED_C:
+        switchState(APPLICATION_STATE_RUNNING_C);
+        break;
+
+        // Waking up a little bit too late, give another chance to do the right thing
+    case APPLICATION_STATE_EXITING_C:
+        runtime_terminate();
+        startTimer(EXIT_TIMER_TIMEOUT);
+        break;
+
+    default:
+        break;
+    }
+}
+
+void RtcBasePlugin::terminatedInd(const int& /*aStatus*/)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    // Only handled if not already in EXITING state,
+    // othervise ignored and deemed as an extra terminated_ind
+    if (mState != APPLICATION_STATE_EXITING_C)
+    {
+        switchState(APPLICATION_STATE_EXITING_C);
+    }
+}
+
+void RtcBasePlugin::processMessage(CommsMessage& message)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    switch (message.getMessageId())
+    {
+    case CORE_MSG_ID_DO_THREAD_DUMP:
+        LOG(EJavaCaptain, EInfo, "sending DO_THREAD_DUMP message to runtime");
+        sendMessageToRuntime(message.getModuleId(), message);
+        break;
+
+    case RTC_MSG_ID_GET_EXTRA_ARGUMENTS:
+        if (message.getSender() == mRuntimeAddress && isRunning())
+        {
+            CommsMessage reply;
+            reply.replyTo(message);
+            setGetExtraArgumentsAck(reply, mRuntimeArguments, mApplicationArguments);
+            LOG2(EJavaCaptain, EInfo, "reply to get runtime attributes: mUid=%S mRuntimeArguments=%S",
+                 mUID.toString().c_str(), mRuntimeArguments.c_str());
+            sendMessageToRuntime(message.getModuleId(), reply);
+        }
+        break;
+
+    default:
+        ELOG1(EJavaCaptain, "Unknown message forwarded to rtcplugin %d", message.getMessageId());
+        break;
+    }
+}
+
+int RtcBasePlugin::sendMessageToRuntime(const int& moduleId, CommsMessage& message)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    message.setReceiver(mRuntimeAddress);
+    message.setModuleId(moduleId);
+
+    return mCore->getComms()->send(message);
+}
+
+bool RtcBasePlugin::isRunning() const
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    return mState == APPLICATION_STATE_RUNNING_C;
+}
+
+void RtcBasePlugin::runtime_init()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    if (mPid > 0 && mCore)
+    {
+        LOG1(EJavaCaptain, EInfo, "Killing process with uid %S",
+             mUID.toString().c_str());
+        mCore->getPmc()->kill(mPid);
+    }
+}
+
+bool RtcBasePlugin::runtime_launch(const int& aLaunchType)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    std::vector<std::string> params;
+    mPid = mCore->getPmc()->launch(generateCommandLine(aLaunchType, params), 0);
+    return mPid > 0;
+}
+
+bool RtcBasePlugin::runtime_relaunch(const int& aLaunchType)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    int status = 0;
+    CommsMessage msg;
+
+    switch (aLaunchType)
+    {
+    case RTC_LAUNCH_TYPE_PUSH_C:
+        setUpdatePushReqParams(msg, mUID);
+        status = sendMessageToRuntime(PLUGIN_ID_RTC_PUSH_C, msg);
+        LOG1(EJavaCaptain, EInfo, "sendUpdatePushMessageToRuntime() returns %d", status);
+        break;
+
+    case RTC_LAUNCH_TYPE_PREWARM_C: // do nothing
+        break;
+
+    default:
+        setLaunchApplicationReqParams(msg, mUID, aLaunchType,
+                                      RTC_LAUNCH_OPTIONS_NONE_C, RTC_LAUNCH_RUNTIME_MIDP_C, mApplicationArguments);
+        status = sendMessageToRuntime(PLUGIN_ID_RTC_C, msg);
+        LOG1(EJavaCaptain, EInfo,
+             "RtcBasePlugin::runtime_relaunch: sendMessageToRuntime() returns %d", status);
+        break;
+    }
+
+    return status == 0;
+}
+
+bool RtcBasePlugin::runtime_terminate()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    CommsMessage terminateMsg;
+    setTerminateApplicationReqParams(terminateMsg, mUID, 0);
+    int status = sendMessageToRuntime(PLUGIN_ID_RTC_C, terminateMsg);
+    LOG1(EJavaCaptain, EInfo, "sendMessageToRuntime() returns %d", status);
+    return status == 0;
+}
+
+void RtcBasePlugin::startTimer(const int& aTimeout)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    // Only cancel if already started
+    if (0 != mTimerId)
+    {
+        mCore->getTimerServer()->timerCancel(mTimerId);
+        mTimerId = 0;
+    }
+    mTimerId = mCore->getTimerServer()->timerCreateSeconds(aTimeout, this);
+}
+void RtcBasePlugin::stopTimer()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+
+    if (0 != mTimerId)
+    {
+        mCore->getTimerServer()->timerCancel(mTimerId);
+        mTimerId = 0;
+    }
+}
+
+void RtcBasePlugin::setPendingLaunch(const int& aType)
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    switch (aType)
+    {
+    case RTC_LAUNCH_TYPE_NORMAL_C:
+        mPendingOperation = PENDING_OPERATION_LAUNCH_NORMAL_C;
+        break;
+
+    case RTC_LAUNCH_TYPE_PUSH_C:
+        mPendingOperation = PENDING_OPERATION_LAUNCH_PUSH_C;
+        break;
+
+    case RTC_LAUNCH_TYPE_AUTO_INVOCATION_C:
+        mPendingOperation = PENDING_OPERATION_LAUNCH_AUTO_INVOCATION_C;
+        break;
+
+    case RTC_LAUNCH_TYPE_BACKGROUND_C:
+        mPendingOperation = PENDING_OPERATION_LAUNCH_BACKGROUND_C;
+        break;
+
+    case RTC_LAUNCH_TYPE_DEBUG_C:
+        mPendingOperation = PENDING_OPERATION_LAUNCH_DEBUG_C;
+        break;
+
+    default:
+        ELOG1(EJavaCaptain, "Unknown pending launch type! (%d)", aType);
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        break;
+    }
+}
+
+void RtcBasePlugin::setPendingTerminate()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    mPendingOperation = PENDING_OPERATION_TERMINATE_C;
+}
+
+void RtcBasePlugin::handlePendingOperations()
+{
+    JELOG4(EJavaCaptain, EInfoHeavyLoad);
+    switch (mPendingOperation)
+    {
+    case PENDING_OPERATION_LAUNCH_NORMAL_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_NORMAL_C));
+        break;
+    case PENDING_OPERATION_LAUNCH_PUSH_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_PUSH_C));
+        break;
+    case PENDING_OPERATION_LAUNCH_AUTO_INVOCATION_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_AUTO_INVOCATION_C));
+        break;
+    case PENDING_OPERATION_LAUNCH_BACKGROUND_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_BACKGROUND_C));
+        break;
+    case PENDING_OPERATION_LAUNCH_DEBUG_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        launch(rtcLaunchInfo(mUID, RTC_LAUNCH_TYPE_DEBUG_C));
+        break;
+    case PENDING_OPERATION_TERMINATE_C:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        terminate(rtcTerminateInfo(mUID));
+        break;
+    case PENDING_OPERATION_NONE_C:
+    default:
+        mPendingOperation = PENDING_OPERATION_NONE_C;
+        break;
+    }
+}
+
+} // namespace captain
+} // namespace java
+