javauis/coreui_akn/src/coreuiavkonimpl.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:23:59 +0300
branchRCL_3
changeset 83 26b2b12093af
parent 66 2455ef1f5bbc
permissions -rw-r--r--
Revision: v2.2.17 Kit: 201041

/*
* Copyright (c) 2009 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: A CoreUi Avkon implementation.
*
*/

#include <string.h>
#include <apgwgnam.h>
#include <akntitle.h>

#include "logger.h"
#include "coreuiavkonimpl.h"
#include "javauiavkonimpl.h"
#include "runtimeexception.h"
#include "javacommonutils.h"

using namespace java::ui;
using namespace java::util;

// ======== STATIC VARIABLES ========

/**
* Singleton
*/

NONSHARABLE_CLASS(CoreUiGlobals)
{
public:
    CoreUiGlobals() : mUiCore(0)
    {
    }

public:
    java::ui::CoreUiAvkonImpl* mUiCore;
};


#if defined(__WINSCW__)

#include <pls.h>
CoreUiGlobals* getCoreUiGlobals()
{
    // Access the PLS of this process
    CoreUiGlobals* globals  =
        Pls<CoreUiGlobals>(TUid::Uid(0x2002703C));
    return globals;
}

#else


static CoreUiGlobals* sGlobals = 0;

CoreUiGlobals* getCoreUiGlobals()
{
    if (sGlobals == 0)
    {
        sGlobals = new CoreUiGlobals(); // codescanner::nonleavenew
    }
    return sGlobals;
}
#endif


CoreUi& getUiInstance()
{
    JELOG2(EJavaUI);
    CoreUiGlobals* globals = getCoreUiGlobals();
    if (globals->mUiCore == 0)
    {
        globals->mUiCore = new CoreUiAvkonImpl(); // codescanner::nonleavenew
    }

    return *globals->mUiCore;
}

void releaseUi()
{
    JELOG2(EJavaUI);
    CoreUiGlobals* globals = getCoreUiGlobals();
    if (globals->mUiCore)
    {
        globals->mUiCore->dispose();
    }
}

EXPORT_C FuncPtr findDllMethod(const char* funcName)
{
    JELOG2(EJavaUI);
    FuncPtr ptr = 0;
    if (strcmp(funcName, "getUiInstance") == 0)
    {
        ptr = (FuncPtr)getUiInstance;
    }
    else if (strcmp(funcName, "releaseUi") == 0)
    {
        ptr = (FuncPtr)releaseUi;
    }
    return ptr;
}

EXPORT_C bool CoreUiAvkon::isCoreUiCreated()
{
    JELOG2(EJavaUI);
    CoreUiGlobals* globals = getCoreUiGlobals();
    return globals->mUiCore != 0;
}

EXPORT_C CoreUiAvkonLcdui& CoreUiAvkonLcdui::getInstance()
{
    JELOG2(EJavaUI);
    return static_cast<CoreUiAvkonLcdui&>(
               static_cast<CoreUiAvkonImpl&>(getUiInstance()));
}

EXPORT_C CoreUiAvkonEswt& CoreUiAvkonEswt::getInstance()
{
    JELOG2(EJavaUI);
    return static_cast<CoreUiAvkonEswt&>(
               static_cast<CoreUiAvkonImpl&>(getUiInstance()));
}

CoreUiAvkonImpl& CoreUiAvkonImpl::getInstanceImpl()
{
    JELOG2(EJavaUI);
    return static_cast<CoreUiAvkonImpl&>(::getUiInstance());
}

CoreUiAvkonImpl::CoreUiAvkonImpl() : mJavaUiAvkonEnv(0), mWgName(0),
        mJavaUiAppUi(0),
        mState(Constructed), mShowStartScreen(true),
        mJavaVm(0), mShutDownPending(false),
        mShutdownTimer(0)
{
    JELOG2(EJavaUI);
    mLock.CreateLocal();

}


CoreUiAvkonImpl::~CoreUiAvkonImpl()
{
    JELOG2(EJavaUI);
    delete mWgName;
    mWgName = 0;
    mLock.Close();
}

void CoreUiAvkonImpl::ensureInitialized(const TUid& appUid,
                                        CoreUiParams* params)
{
    JELOG2(EJavaUI);
    if (mJavaUiAvkonEnv == 0)
    {
        java::util::Uid uid;
        TUidToUid(appUid, uid);

        start(uid, params);
    }
}


CoreUiAvkonLcduiSupport& CoreUiAvkonImpl::getLcduiSupport()
{
    return mLcduiSupport;
}

CoreUiAvkonEswtSupport& CoreUiAvkonImpl::getEswtSupport()
{
    return mEswtSupport;
}

void CoreUiAvkonImpl::start(const java::util::Uid& midletUid,
                            CoreUiParams* uiParams)
{
    mMidletUid = midletUid;
    if (uiParams != 0)
    {
        mCoreUiParams = *uiParams;
    }
    mLcduiSupport.startUiThread(*this);
}

void CoreUiAvkonImpl::startScheduler()
{
    JELOG2(EJavaUI);
    if (mJavaUiAvkonEnv != 0)
    {
        mState = CoreUiCreated;
        mJavaUiAvkonEnv->ExecuteD();
        cancelShutdownTimer();
        mEswtSupport.dispose();
        mJavaUiAvkonEnv = 0;
        delete mWgName;
        mWgName = 0;
    }
    mState = Destroyed;
}

void CoreUiAvkonImpl::createUi()
{
    JELOG2(EJavaUI);
    // Construct the environment (EikonEnv + AppUi + server)

    // The cleanup stack is created here
    mJavaUiAvkonEnv = new CEikonEnv; // codescanner::nonleavenew

    if (mJavaUiAvkonEnv != 0)
    {
        uidToTUid(mMidletUid, mMidletTUid);
        if (mMidletUid == Uid(L"[2001843a]") || // Is it installer.
                mMidletUid == Uid(L"[2002121e]"))    // Is it TCK runner.
        {
            mShowStartScreen = false;
        }
        TRAPD(status, initAvkonUiL());
        if (status != KErrNone)
        {
            // Deletes AS and CleanupTrap. No need to call 'delete env'.
            mJavaUiAvkonEnv->DestroyEnvironment();
            std::string errorStr("Ui creation failed: ");
            errorStr.append(JavaCommonUtils::intToString(status));
            throw java::runtime::RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
        }
        mEswtSupport.uiThreadInit();
    }
}

void CoreUiAvkonImpl::initAvkonUiL()
{
    JELOG2(EJavaUI);
    TApaApplicationFactory appFactory(newJavaApplication);

    CApaCommandLine* appCmdLine = CApaCommandLine::NewLC();
    appCmdLine->SetExecutableNameL(KNullDesC);          // None - app function provided by the app factory
    appCmdLine->SetDefaultScreenL(0);
    appCmdLine->SetServerNotRequiredL();                //
    if (mCoreUiParams.isBackgroundStart())
    {
        appCmdLine->SetCommandL(EApaCommandBackground);
    }
    mJavaUiAvkonEnv->DisableExitChecks(ETrue);
    mJavaUiAvkonEnv->ConstructAppFromCommandLineL(appFactory, *appCmdLine);

    CleanupStack::PopAndDestroy(appCmdLine);

    mJavaUiAvkonEnv->AppUiFactory()->StatusPane()->MakeVisible(EFalse);


    // Contruct the WindowsGroupName, used to change the displayed name in the tasklist
    mWgName = CApaWindowGroupName::NewL(mJavaUiAvkonEnv->WsSession());
    mWgName->SetRespondsToSwitchFilesEvent(EFalse);
    mWgName->SetRespondsToShutdownEvent(ETrue);
    mWgName->SetHidden(EFalse);
    mWgName->SetAppUid(mMidletTUid);
    mWgName->SetWindowGroupName(mJavaUiAvkonEnv->RootWin());

    mJavaUiAvkonEnv->RootWin().EnableReceiptOfFocus(ETrue);
}


void CoreUiAvkonImpl::dispose()
{
    JELOG2(EJavaUI);
    bool canBeDisposed = mJavaUiAppUi == 0 ||
                         (mJavaUiAppUi && mJavaUiAppUi->isClosingPossible());
    if (canBeDisposed)
    {
        if (mState != Destroyed)
        {
            mLcduiSupport.closeUi();
        }
        delete this;
        CoreUiGlobals* globals = getCoreUiGlobals();
        globals->mUiCore = 0;
    }
}

CApaWindowGroupName* CoreUiAvkonImpl::getWindowGroupName() const
{
    JELOG2(EJavaUI);
    return mWgName;
}

bool  CoreUiAvkonImpl::showStartScreen() const
{
    JELOG2(EJavaUI);
    return mShowStartScreen && mCoreUiParams.getScreenMode() != NO_START_SCREEN;
}


CoreUiAvkonAppUi* CoreUiAvkonImpl::getJavaUiAppUi() const
{
    JELOG2(EJavaUI);
    return mJavaUiAppUi;
}

CAknAppUi* CoreUiAvkonImpl::getJavaAknAppUi() const
{
    JELOG2(EJavaUI);
    return mJavaUiAppUi;
}

void CoreUiAvkonImpl::setJavaUiAppUi(JavaUiAvkonAppUi* appUi)
{
    JELOG2(EJavaUI);
    mJavaUiAppUi = appUi;
}

RHeap* CoreUiAvkonImpl::getProcessHeap() const
{
    JELOG2(EJavaUI);
    return mLcduiSupport.getProcessHeap();
}

RHeap* CoreUiAvkonImpl::getUiThreadHeap() const
{
    JELOG2(EJavaUI);
    return mLcduiSupport.getUiThreadHeap();
}


bool CoreUiAvkonImpl::setJavaVm(JNIEnv* env)
{
    JELOG2(EJavaUI);
    mLock.Wait();
    bool result = false; // Meaning the starting of the MIDlet
    // should not be allowed.
    LOG(EJavaUI, EInfo, "Setting JavaVm");
    if (!mShutDownPending)
    {
        LOG(EJavaUI, EInfo, "  No pending shutdown");
        env->GetJavaVM(&mJavaVm); // Get pointer to VM
        if (mJavaVm)
        {
            LOG(EJavaUI, EInfo, "  Got the VM");
            result = true;
        }
        else
        {
            ELOG(EJavaUI, "JNI attachUiToVm(), GetJavaVM(() failed");
        }
    }
    mLock.Signal();
    LOG1(EJavaUI, EInfo, "CoreUiAvkonImpl::setJavaPeer result = %d", result);
    return result;
}

void CoreUiAvkonImpl::shutDownRequestFromWindowServer()
{
    JELOG2(EJavaUI);
    LOG(EJavaUI, EInfo, "shutDownRequestFromWindowServer");
    mLock.Wait();
    if (mState != ShuttingDown)
    {
        mState = ShuttingDown;
        if (mShutdownTimer == 0)
        {
            TRAP_IGNORE(setShutdownTimerL());
        }
        LOG(EJavaUI, EInfo, "  mState != SHUTTING_DOWN");
        if (mJavaVm) // Check if the VM already running.
        {
            LOG(EJavaUI, EInfo, "  We have the VM");

            bool success =
                callStaticVoidJavaMethod("com/nokia/mj/impl/coreui/CoreUi",
                                         "shutdownRequest",
                                         "()V");

            if (!success)
            {
                ELOG(EJavaUI, "Killing process forcefully");
                RProcess().Kill(-1);
            }


        }
        else
        {
            LOG(EJavaUI, EInfo, "  Pending request");
            // No, pend the request.
            mShutDownPending = true;
        }
    }
    mLock.Signal();
}

bool CoreUiAvkonImpl::callStaticVoidJavaMethod(const char* className,
        const char* methodName,
        const char* methodSignature,
        ...)
{
    JELOG2(EJavaUI);
    bool success = false;

    JNIEnv* env;
#ifdef RD_JAVA_UITHREAD_OWN_HEAP
    User::SwitchHeap(getProcessHeap());
#endif // RD_JAVA_UITHREAD_OWN_HEAP
    int result = mJavaVm->AttachCurrentThread((void**)&env, 0);
    if (result == 0)
    {
        LOG(EJavaUI, EInfo, "  VM Attached");
        jclass clz = env->FindClass(className);
        if (clz != 0)
        {
            LOG(EJavaUI, EInfo, "  jclass created");
            jmethodID methodId =
                env->GetStaticMethodID(clz, methodName, methodSignature);
            if (methodId != 0)
            {
                LOG(EJavaUI, EInfo, "  methodId created");
                va_list args;
                va_start(args, methodSignature);
                env->CallStaticVoidMethodV(clz, methodId, args);
                LOG(EJavaUI, EInfo, "  CallStaticVoidMethodV done");
                va_end(args);
                // Close message sent successfully to Java side.
                success = true;
            }
            else
            {
                ELOG(EJavaUI, "callStaticVoidJavaMethod, "
                     "GetMethodID(() failed");
            }
            env->DeleteLocalRef(clz);
        }
        else
        {
            ELOG(EJavaUI, "callStaticVoidJavaMethod, "
                 "GetObjectClass() failed");
        }
        result = mJavaVm->DetachCurrentThread();
        LOG1(EJavaUI, EInfo, "  DetachCurrentThread done, st = %d", result);
    }
    else
    {
        ELOG(EJavaUI, "callStaticVoidJavaMethod, "
             "AttachCurrentThread() failed");
    }
#ifdef RD_JAVA_UITHREAD_OWN_HEAP
    User::SwitchHeap(getUiThreadHeap());
#endif // RD_JAVA_UITHREAD_OWN_HEAP
    return success;
}

void CoreUiAvkonImpl::setShutdownTimerL()
{
    JELOG2(EJavaUI);
    LOG(EJavaUI, EInfo, "setShutdownTimerL");
    mShutdownTimer = CPeriodic::NewL(CActive::EPriorityStandard);
    mShutdownTimer->Start(8000000, 1000000,
                          TCallBack(shutdownTimerCallback, 0));
}

void CoreUiAvkonImpl::cancelShutdownTimer()
{
    JELOG2(EJavaUI);
    LOG(EJavaUI, EInfo, "cancelShutdownTimer");
    if (mShutdownTimer)
    {
        if (mShutdownTimer->IsActive())
        {
            LOG(EJavaUI, EInfo, "  It was active");
            mShutdownTimer->Cancel();
        }
        delete mShutdownTimer;
        mShutdownTimer = 0;
    }
}

TInt CoreUiAvkonImpl::shutdownTimerCallback(TAny*)
{
    JELOG2(EJavaUI);
    ELOG(EJavaUI, "Killing process forcefully due to timer");
    RProcess().Kill(-1);
    return 0;
}