locationrequestmgmt/locationserver/src/EPos_CPosServer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 17 Sep 2010 08:37:32 +0300
changeset 60 9a7e3d5f461a
parent 51 95c570bf4a05
permissions -rw-r--r--
Revision: 201037 Kit: 201037

// Copyright (c) 2005-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:
// INCLUDE FILES
//



#include <e32base.h>
#include <e32svr.h>
#include <ecom/ecom.h>
#include <connect/sbdefs.h>

//#include <LbsIpc.h>
//#include <StartPosServer.h>
#include <lbsipc.h>
#include "lbslocservermessageenums.h"
#include "EPos_CPosResourceReader.h"
#include <eposserver.rsg>
#include <lbs/epos_mposmodulesobserver.h>
#include <centralrepository.h>
#ifdef SYMBIAN_FEATURE_MANAGER
	#include <featdiscovery.h>
	#include <featureuids.h>
#endif
#include "epos_cposmodulessettings.h"
#include "EPos_CPosServer.h"
#include "EPos_ServerPanic.h"
#include "EPos_CPosSession.h"
#include "EPos_CPosServerDelayedShutdown.h"
#include "EPos_CPosModulesStatus.h"
#include "EPos_CPosLocMonitorReqHandlerHub.h"
#include "lbsrootcenrepdefs.h"

#include "EPos_Global.h"
#include "lbspositioningstatusprops.h"

// CONSTANTS
_LIT(KPosResourceFile, "\\private\\101F97B2\\eposserver.rsc");

#ifdef _DEBUG
_LIT(KTraceFileName, "EPos_CPosServer.cpp");
#endif

// ================= SERVER'S POLICY =======================

//Definition of the ranges of IPC numbers
const TInt eposServerPolicyRanges[] = 
    {
	0,
	ELbsServerCancelAsyncRequest,
	ELbsGetDefaultModuleId,
	ELbsEmptyLastKnownPositionStore,
	ELbsServerLastMessageId,
	
	ELbsPositionerCancelAsyncRequest,
	ELbsPositionerOpen,
	ELbsPositionerClose,
	ELbsSetSingleRequestor,
	ELbsPositionerLastMessageId,
	ELbsPositionCustomCodesFirst
    }; 
    
// Total number of ranges
const TUint eposServerPolicyRangeCount = 
    sizeof(eposServerPolicyRanges) / sizeof(TInt);

// Types of Policies
enum TPolicies
    {
    EPolicyLocationNeeded = 0,
    EPolicyWriteUserDataNeeded,
    };

// Specific capability checks
const CPolicyServer::TPolicyElement eposServerPolicyElements[] = 
    {
    // policy EPolicyLocationNeeded - fail call if Location not present
    {_INIT_SECURITY_POLICY_C1(ECapabilityLocation), CPolicyServer::EFailClient},
    // policy EPolicyWriteUserDataNeeded - fail call if WriteUserData capability not present
    {_INIT_SECURITY_POLICY_C1(ECapabilityWriteUserData), CPolicyServer::EFailClient}
    };

//Policy to implement for each of the above ranges        
const TUint8 eposServerPolicyElementsIndex[eposServerPolicyRangeCount] = 
    {
    CPolicyServer::ENotSupported,
    CPolicyServer::EAlwaysPass,	            // server cancel
    EPolicyLocationNeeded,                  // GetDefModId -> NotifyModStatusEv
    EPolicyWriteUserDataNeeded,				// Empty Last Known position store 
    CPolicyServer::ENotSupported,           // reserved server's codes
    CPolicyServer::EAlwaysPass,	            // positioner cancel
    CPolicyServer::EAlwaysPass,	            // open methods
    CPolicyServer::EAlwaysPass,	            // close positioner
    EPolicyLocationNeeded,                  // SetSingReq -> GetLastKnownPositionArea
    CPolicyServer::ENotSupported,           // reserved positioner's codes
    CPolicyServer::ECustomCheck             // custom requests
    };

//Package all the above together into a policy
const CPolicyServer::TPolicy eposServerPolicy =
    {
    CPolicyServer::EAlwaysPass,             // onConnect
    eposServerPolicyRangeCount,	            // number of ranges                                   
    eposServerPolicyRanges,	                // ranges array
    eposServerPolicyElementsIndex,	        // elements<->ranges index
    eposServerPolicyElements,		        // array of elements
    };
        
// ================= MEMBER FUNCTIONS =======================

/**
 * C++ constructor.
 *
 * @param aPriority Priority at which to run the server active object.
 * @param aPolicy Reference to a policy object describing the security 
 *                checks required for each message type.
 * @param aServerType Sharable or non-sharable sessions.
 */
CPosServer::CPosServer(TInt aPriority, const TPolicy &aPolicy, TServerType aServerType)
        : CPolicyServer(aPriority, aPolicy, aServerType)
    {
    }

/**
 * Symbian default constructor.
 */
void CPosServer::ConstructL() 
    {
#if defined __WINSCW__ && defined SYMBIAN_CELLMO_CENTRIC
	TBool LocationManagementSupported = EFalse;
#else
#ifdef SYMBIAN_FEATURE_MANAGER
	TBool LocationManagementSupported = CFeatureDiscovery::IsFeatureSupportedL(NFeature::KLocationManagement);
#else
	__ASSERT_ALWAYS(EFalse, User::Invariant());	// Would happen on older versions of symbian OS if this code ever backported
#endif // SYMBIAN_FEATURE_MANAGER
#endif // __WINSCW__ && defined SYMBIAN_CELLMO_CENTRIC

	
#if defined __WINSCW__	
	if(LocationManagementSupported && !FindRootProcess())
		{
        _LIT(KLbsRootFileName, "\\sys\\bin\\lbsroot.exe");
	    _LIT(KLbsRootProcessName, "lbsroot.exe");
	    _LIT(KLbsCommandLine, "");
        RProcess process;
        TInt r=process.Create(KLbsRootProcessName,KLbsCommandLine);
        if (r!=KErrNone)
            {
            User::Leave(r);
            }
        TRequestStatus stat;
        process.Rendezvous(stat);
        if (stat!=KRequestPending)
            {
            process.Kill(0);
            }
        else
            {
            process.Resume();
            }
        User::WaitForRequest(stat);
        r=(process.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
        
        process.Close();
        if (r!=KErrNone)
            {
            User::Leave(r);
            }
		}
#endif // WINSCW

    // Backup listener
    DEBUG_TRACE("Checking for backup or restore...", __LINE__)
    iBackupListener = CPosBackupListener::NewL();
    if (iBackupListener->IsBackupOperationOngoing())
        {
        User::Leave(KErrNotReady);
        }
    iBackupListener->Start(*this);

    
    // Settings and last position handler
    CPosResourceReader* resources = CPosResourceReader::NewLC(KPosResourceFile);
    iServerShutdownDelay = resources->ReadInt32L(R_POS_SERVER_SHUTDOWN_DELAY);
    
    TInt dumpInterval = resources->ReadInt32L(R_POS_SERVER_DUMP_INTERVAL);

    //DEBUG_TRACE("Reading last known position...", __LINE__)
    //    HBufC* lastKnownPositionFileName = resources->ReadHBufCL(R_LAST_KNOWN_POSITION_FILENAME);
    //    CleanupStack::PushL(lastKnownPositionFileName);
    iLocMonitorReqHandlerHub = CPosLocMonitorReqHandlerHub::NewL(); 

    
    CleanupStack::PopAndDestroy(resources);

    // Shutdown timer
    iShutdown = CPosServerDelayedShutdown::NewL();

    
    DEBUG_TRACE("Opening Location Settings...", __LINE__)
    // Location Settings
    iModuleSettings = CPosModuleSettings::NewL();
    iModulesStatus = CPosModulesStatus::NewL(iModuleSettings->PosModules());
    DEBUG_TRACE("Setting Location Settings observer...", __LINE__)
    iModuleSettings->AddListenerL(*this);

    // Define the MO Positioning Status property
	LbsPositioningStatusProps::InitializeMoPropertyL();	

	// Reset the key to zero
    TInt posStatusCategory;
    
    CRepository* rep = CRepository::NewLC(KLbsCenRepUid);
    TInt err = rep->Get(KMoPositioningStatusAPIKey, posStatusCategory);
    if( err == KErrNone )
        {
        err = RProperty::Set(TUid::Uid(posStatusCategory), KLbsMoPositioningStatusKey,0);
        }
    CleanupStack::PopAndDestroy(rep);

    DEBUG_TRACE("Starting server active object...", __LINE__)
    StartL(KPositionServerName);
    }

/**
 * Two-phased constructor.
 */
CPosServer* CPosServer::NewL()
    {
    CPosServer* self = new (ELeave) CPosServer(EPriority, eposServerPolicy);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }

/**
 * Destructor.
 */
CPosServer::~CPosServer()
    {
    delete iLocMonitorReqHandlerHub;
    
    delete iShutdown;
    delete iModulesStatus;
    delete iModuleSettings;
    delete iBackupListener;
   
    
    // This is needed because CPositioner might have used ECom (PSYs)
    REComSession::FinalClose();
    }

/**
 * From MPosModuleSettingsListener.
 *
 * Called when a change has been detected in the modules database.
 * @param aEvent Event information
 */
void CPosServer::HandleModuleSettingsChangedL(TPosModulesEvent aEvent)
    {
    // Notify iModuleStatus
    iModulesStatus->HandleSettingsChangeL(aEvent);

    // For all sessions, call HandleSettingsChangeL()
    iSessionIter.SetToFirst();
    CPosSession* session = static_cast <CPosSession*> (iSessionIter++);
    while (session)
        {
        session->HandleSettingsChangeL(aEvent);
        session = static_cast <CPosSession*> (iSessionIter++);
        }
    }

/** 
 * From MPosBackupEventCallback
 *
 * Called by iBackupListener when a backup or restore 
 * operation either starts. Shuts down the server.
 */
void CPosServer::HandleBackupOperationEventL()
    {
    
    DEBUG_TRACE("HandleBackupOperationEventL", __LINE__)
    conn::TBURPartType state = conn::EBURUnset;
    conn::TBackupIncType type = conn::ENoBackup;
    iBackupListener->GetCurrentValue(state, type);

    // At the moment it just shuts down if backup/restore is in progress
    if ((state != conn::EBURUnset) && (state != conn::EBURNormal))
        {
        iSessionIter.SetToFirst();
        CPosSession* session = static_cast <CPosSession*> (iSessionIter++);
        while (session)
            {
            session->NotifyServerShutdown();
            session = static_cast <CPosSession*> (iSessionIter++);
            }

        // Shutdown the server by shutting down the active scheduler.
        CActiveScheduler::Stop();
        }
    else
        {
        iBackupListener->Start(*this); // continue listening
        }
    }

/**
 * From CServer2
 */
CSession2* CPosServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
    {
    // Check we're the right version
    TVersion version(KPosMajorVersionNumber,
                     KPosMinorVersionNumber,
                     KPosBuildVersionNumber);
    if (!User::QueryVersionSupported(version, aVersion))
        {
        User::Leave(KErrNotSupported);
        }

    // Make new session
    CPosSession* newSession = 
        CPosSession::NewL(
            *(const_cast<CPosServer*>(this)), 
            *iModuleSettings,
            *iModulesStatus, 
            *iLocMonitorReqHandlerHub);

    return newSession;
    }

/**
 * From CPolicyServer
 */
CPolicyServer::TCustomResult CPosServer::CustomSecurityCheckL(const RMessage2& /*aMsg*/, TInt& /*aAction*/,TSecurityInfo& /*aMissing*/)
    {
    DEBUG_TRACE("CustomSecurityCheck", __LINE__)
    return CPolicyServer::EFail;
    }

/**
 * Increment number of sessions
 */
void CPosServer::IncrementSessions()
    {
    DEBUG_TRACE("IncrementSessions", __LINE__)

    iNumSessions++;
    iShutdown->Cancel();
    }

/**
 * Decrement number of sessions
 */
void CPosServer::DecrementSessions()
    {    
    DEBUG_TRACE("DecrementSessions", __LINE__)

    // This panic handles an internal error.
    __ASSERT_DEBUG(iNumSessions > 0,
        DebugPanic(EPosServerPanicSessionsCountInconsistency));

    if (--iNumSessions == 0)
        {
        iShutdown->Start(iServerShutdownDelay);
        }
    }

TBool CPosServer::FindRootProcess()
	{
	_LIT(KLbsRootProcessName, "lbsroot.exe*");
	TInt err(KErrNotFound);
	TFullName fullName;			
	TFindProcess processFinder(KLbsRootProcessName);
	while (err = processFinder.Next(fullName), err == KErrNone)
		{
		RProcess process;
		TInt processOpenErr = process.Open(processFinder);
		if (processOpenErr == KErrNone)
			{
			TExitType exitType = process.ExitType();
			if (exitType == EExitPending)
				{
				// Found a running instance of lbsroot.exe,
				return ETrue;
				}
			}
		process.Close();		
		}
		
	return EFalse;
	}
//  End of File