omadrm/drmengine/drmclock/Src/GPSWatcher.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 11 May 2010 16:28:38 +0300
branchRCL_3
changeset 32 457cd4423b8c
parent 20 a20e54f39dd4
permissions -rw-r--r--
Revision: 201017 Kit: 201019

/*
* 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

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


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

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

    iTimeUpdaters.ResetAndDestroy();
	iActiveSatelliteModules.ResetAndDestroy();
    
    delete iStatusUpdater;
	}

// -----------------------------------------------------------------------------
// 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()
	{
    TRequestStatus* status = &iStatus;    	    
	CTimer::ConstructL();

    // Create the status updater
    iStatusUpdater = CPosIntGpsHwStatus::NewL(*this);
        
    // Get the status manually, if we can, it's ok if we cant
    TRAP_IGNORE( iStatusUpdater->GetStatusL( iGpsStatus ) );
    
    if( !IsActive() )
        {
        SetActive();    
        }
        
    User::RequestComplete(status, KErrNone);   
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::OnStatusUpdateEvent
// Inherited from MPosIntGpsHwStatusObserver
// -----------------------------------------------------------------------------
//
void CGPSWatcher::OnStatusUpdateEvent(CPosIntGpsHwStatus::TIntGpsHwStatus aStatus, TInt aError)
    {
    TRequestStatus* status = &iStatus;    
    
    // store the status from the Gps:
    iGpsStatus = aStatus;
        
    User::RequestComplete(status, aError);

    if( !IsActive() )
        {        
        SetActive();
        }    
    }

// -----------------------------------------------------------------------------
// CGPSWatcher::RunL
// Inherited from CActive
// -----------------------------------------------------------------------------
//
void CGPSWatcher::RunL()
	{
    TInt error = KErrNone;
    
	// If there are errors just leave and stop watching:    
	DRMLOG2(_L("CGPSWatcher::RunL: status: '%d'"), iStatus.Int());   

    switch( iGpsStatus )
        {
        // GPS HW is used and is receiving location fixes.
        case CPosIntGpsHwStatus::EStatusOn:
            DRMLOG(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusOn: Checking modules"));
            // No active modules, check again:
            if( !iActiveSatelliteModules.Count() )
                {
                DRMLOG(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusOn: No active modules in list Checking modules"));    
                error = CheckModules();    
                }
            
            // if we have some or found some check the satellites for updates:    
            if( !error && iActiveSatelliteModules.Count() )
                {
                DRMLOG2(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusOn: Active modules available (%d), check satellites"), iActiveSatelliteModules.Count());                     
                // Get the time update:
                CheckSatellites();   
                }
            else
                {
                DRMLOG2(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusOn: Still no active modules in list or error (%d) occurred"), error);                     
                }        
            break;  
        // GPS HW is used and is searching for location.
        case CPosIntGpsHwStatus::EStatusActive:
            // Get a list of active GPS modules:
            DRMLOG(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusActive: Checking modules"));
            
            // return value not important:
            CheckModules();
            break;
        case CPosIntGpsHwStatus::EStatusUnknown:
        case CPosIntGpsHwStatus::EStatusOff:
            // Clear the list of modules:
            DRMLOG2(_L("CGPSWatcher::RunL: CPosIntGpsHwStatus::EStatusUnknown,Off or default: (%d) Checking modules"), iGpsStatus);            
            iActiveSatelliteModules.ResetAndDestroy();  
            iTimeUpdaters.ResetAndDestroy();         
        default:
            // Do nothing    
            break;   
        }		
	}


// -----------------------------------------------------------------------------
// CGPSWatcher::DoCancel
// Inherited from CActive
// -----------------------------------------------------------------------------
//
void CGPSWatcher::DoCancel()
	{
	}

// -----------------------------------------------------------------------------
// CGPSWatcher::RunError
// Inherited from CActive
// -----------------------------------------------------------------------------
//
TInt CGPSWatcher::RunError( TInt /*aError*/ )
    {
    // ignore errors    
    return KErrNone;    
    }
	
// -----------------------------------------------------------------------------
// CGPSWatcher::CheckModules
// Check what modules are present and act accordingly
// -----------------------------------------------------------------------------
//
TInt CGPSWatcher::CheckModules()
	{
	TUint numModules = 0;
	TPositionModuleInfo* moduleInfo = NULL;
	TInt error = KErrNone;
	RPositionServer posServer;
	
	// Destroy the old list:
	iActiveSatelliteModules.ResetAndDestroy();
		    
	// open connection to the positioning server:	    
    error = posServer.Connect();		    
	if( error )
	    {
	    return error;    
	    }	    
		    
    error = posServer.GetNumModules( numModules );		    
		    
	if(error || !numModules)
	    {
        DRMLOG2(_L("CheckModules: modules available (%d)"), numModules);	  
        DRMLOG2(_L("CheckModules: error code (%d)"), error);	          
      
		return KErrNotFound;
        }
        
	for( TUint i = 0; i < numModules; i++)
		{
		if(!moduleInfo)
			{
			moduleInfo = new TPositionModuleInfo;
            if( !moduleInfo )
                {
                // in practice OOM situation
                posServer.Close();    
                return KErrNoMemory;    
                }
			}
		
		// Get module info from the server
		if(posServer.GetModuleInfoByIndex(i, *moduleInfo) != KErrNone)
		    {
			continue;
            }

        DRMLOG(_L("CheckModules: Checking for internal & satellite capable"));	
                        
		// 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 and check if the module is actually active:


        DRMLOG(_L("CheckModules: Checking module status"));	
        		
		TPositionModuleStatus moduleStatus;
		
		if(posServer.GetModuleStatus(moduleStatus, moduleInfo->ModuleId()) != KErrNone)
		    {
			continue;
		    }

		// Check if the module is active or ready as all might not use the active state:
		if(!(moduleStatus.DeviceStatus() == TPositionModuleStatus::EDeviceActive ||
		     moduleStatus.DeviceStatus() == TPositionModuleStatus::EDeviceReady) ) 
		    {
			continue;
		    }


        DRMLOG(_L("CheckModules: Module is ready or active"));	
			
		// Active internal satellite device, try to append in the array
		if(iActiveSatelliteModules.Append(moduleInfo) == KErrNone)
		    {
		    // Set this to 0 so that on the next round a new one will be created
		    // old one will be in the list:   
            DRMLOG2(_L("CheckModules: Appended modules to list available (%d) active now available"), iActiveSatelliteModules.Count());		     
			moduleInfo = 0;
		    }
		}
	
	// There is a module created which was not added, delete it.	
	if( moduleInfo )
	    {
	    delete moduleInfo;
	    moduleInfo = NULL;    
	    }	
	
	// close connection to the positioning server:    
	posServer.Close();
	return KErrNone;
	}


// -----------------------------------------------------------------------------
// CGPSWatcher::CheckSatellites()
// Check what modules are present and act accordingly
// -----------------------------------------------------------------------------
//
void CGPSWatcher::CheckSatellites()
    {
    CGPSTimeUpdater* updater = NULL;
        
    iTimeUpdaters.ResetAndDestroy();
        
    // Start as many updaters as needed:    
    for( TInt i = 0; i < iActiveSatelliteModules.Count(); i++ )
        {
        updater = CGPSTimeUpdater::New( iActiveSatelliteModules[i]->ModuleId(), iClock );
        if( updater )
            {
            if( iTimeUpdaters.Append(updater) ) 
                {
                delete updater;
                updater = NULL;    
                }
            }
        }    
    }
    
// End of File