omadrm/drmengine/drmclock/Src/GPSWatcher.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:14:55 +0300
changeset 23 493788a4a8a4
child 31 908beac81e0a
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2010 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:  Implementation of the GPS Watcher
*
*/


// INCLUDE FILES
#include <e32base.h>
#include <e32svr.h>

#include "GPSWatcher.h"
#include "GPSTimeUpdater.h"
#include "DRMClock.h"
#include "drmlog.h"

// Wait time in microseconds: wait 5 minutes
const TInt KGpsDefaultWaitTime = 300000000;
const TInt KMaxRetryCounter = 20;

// ============================ MEMBER FUNCTIONS ===============================


// -----------------------------------------------------------------------------
// CGPSWatcher::CGPSWatcher
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//   
CGPSWatcher::CGPSWatcher( CDRMClock* aClock ) :
	CTimer(EPriorityHigh),
	iClock( aClock ),
	iRetryCounter( 0 )
	{
	CActiveScheduler::Add(this);
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::~CGPSWatcher
// C++ destructor
// -----------------------------------------------------------------------------
// 
CGPSWatcher::~CGPSWatcher()
	{
	Cancel();

	delete iTimeUpdater; 
	iTimeUpdater = 0; 
	
	iPosServer.Close();
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::NewL
// Two-phased constructor
// -----------------------------------------------------------------------------
//
CGPSWatcher* CGPSWatcher::NewL( CDRMClock* aClock )
	{
	CGPSWatcher* self = new (ELeave) CGPSWatcher( aClock );
	
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	
	return self;
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CGPSWatcher::ConstructL()
	{
	CTimer::ConstructL();

	User::LeaveIfError(iPosServer.Connect());
	
	// Immediately subscribe for module status events
	iStatusEvent.SetRequestedEvents(TPositionModuleStatusEventBase::EEventDeviceStatus);
	Subscribe();

	// Check initial state
	CheckModules();
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::Subscribe
// Subscribe to position events
// -----------------------------------------------------------------------------
//
void CGPSWatcher::Subscribe()
	{
	iPosServer.NotifyModuleStatusEvent(iStatusEvent, iStatus);
	SetActive();
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::RunL
// Inherited from CActive
// -----------------------------------------------------------------------------
//
void CGPSWatcher::RunL()
	{
	// If there are errors just leave and stop watching:    
	DRMLOG2(_L("CGPSWatcher::RunL: error: '%d'"), iStatus.Int());   
    	        
	// If we already updated the time:
	if( iTimeUpdater && iTimeUpdater->TimeReceived() )
	    {
	    DRMLOG( _L("CGPSWatcher::RunL: time updater exists, time received, deleting"));    
	    iClock->Notify( CDRMClock::ENotifyGPSTimeReceived );    
	    DRMLOG( _L("CGPSWatcher::RunL: object deleted, returning"));
	    return;    
	    }

	// The server was killed:
    if( iStatus.Int() == KErrServerTerminated )
        {
        if( iRetryCounter > KMaxRetryCounter )
            {
            DRMLOG( _L("CGPSWatcher::RunL: Maximum retries reached, stopping watcher.") );    
            iClock->Notify( CDRMClock::ENotifyGPSTimeReceived );
            return;         
            }    
	    // If there are errors just leave and stop watching:    
	    DRMLOG2(_L("CGPSWatcher::RunL: server terminated, waiting '%d' microseconds"), KGpsDefaultWaitTime);               
        After( TTimeIntervalMicroSeconds32(KGpsDefaultWaitTime) );
        return;    
        }	  
	    
	Subscribe();
	TPositionModuleStatusEventBase::TModuleEvent occurredEvents = iStatusEvent.OccurredEvents();
	DRMLOG2(_L("CGPSWatcher::RunL: occurredEvents = 0x%X"), occurredEvents);
	
	
	// If time updater is not running, check module statuses
	if(!iTimeUpdater)
		CheckModules();
	}


// -----------------------------------------------------------------------------
// CGPSWatcher::DoCancel
// Inherited from CActive
// -----------------------------------------------------------------------------
//
void CGPSWatcher::DoCancel()
	{
	iPosServer.CancelRequest(EPositionServerNotifyModuleStatusEvent);
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::RunError
// Inherited from CActive
// -----------------------------------------------------------------------------
//
TInt CGPSWatcher::RunError( TInt /*aError*/ )
    {
    // ignore errors    
    return KErrNone;    
    }
	
// -----------------------------------------------------------------------------
// CGPSWatcher::CheckModules
// Check what modules are present and act accordingly
// -----------------------------------------------------------------------------
//
void CGPSWatcher::CheckModules()
	{
	// Get number of modules
	TUint numModules;
	if(iPosServer.GetNumModules(numModules)!=KErrNone || !numModules)
		return;
	
	// Collect all active and satellite capable modules
	TFullName moduleName;
	RPointerArray<TPositionModuleInfo> satelliteModules;
	
	TPositionModuleInfo *moduleInfo(0);
	
	for(TUint i=0; i<numModules; i++)
		{
		if(!moduleInfo)
			{
			moduleInfo = new TPositionModuleInfo;
			if(!moduleInfo)
			    {   
				continue;
			    }
			}
		
		// Get module info from the server
		if(iPosServer.GetModuleInfoByIndex(i, *moduleInfo) != KErrNone)
		    {
			continue;
            }
            
		// Check if the module is internal and satellite capable		
		if(! (moduleInfo->DeviceLocation() & TPositionModuleInfo::EDeviceInternal) ||
		   ! (moduleInfo->Capabilities() & TPositionModuleInfo::ECapabilitySatellite) )
			{
			// Not internal or satellite capable
			continue;
			}
		
		// Get module status
		TPositionModuleStatus moduleStatus;
		if(iPosServer.GetModuleStatus(moduleStatus, moduleInfo->ModuleId()) != KErrNone)
		    {
			continue;
		    }
		// Check if the module is active
		if(moduleStatus.DeviceStatus() != TPositionModuleStatus::EDeviceActive) 
		    {
			continue;
		    }

		moduleInfo->GetModuleName(moduleName);
		
		DRMLOG6( _L("Module %d: id=0x%08X, name = %S, cap=0x%08X, status=%d"), i, moduleInfo->ModuleId().iUid, &moduleName, moduleInfo->Capabilities(), moduleStatus.DeviceStatus());
			
		// Active internal satellite device, try to append in the array
		if(satelliteModules.Append(moduleInfo) == KErrNone)
		    {
			moduleInfo = 0;
		    }
		}
	
	delete moduleInfo;
	
	if(satelliteModules.Count())
		{
		DRMLOG( _L("Active satellite module available") );    
		// We have an active satellite module available
		TPositionModuleId moduleId = satelliteModules[0]->ModuleId();
		
		// Just allocating/deleting the time updater will do the trick
		iTimeUpdater = CGPSTimeUpdater::New(iPosServer, moduleId, iClock);
		}
	else
		{
		DRMLOG( _L("No active satellite modules available") );    
		// Delete time updater since no active GPS anymore
		delete iTimeUpdater; iTimeUpdater = 0;
		}
	
	satelliteModules.ResetAndDestroy();
	satelliteModules.Close();
	}