omadrm/drmengine/drmclock/Src/DRMClock.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:41:43 +0200
branchRCL_3
changeset 18 8a03a285ab14
parent 0 95b198f216e5
permissions -rw-r--r--
Revision: 201009 Kit: 201010

/*
* Copyright (c) 2003-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:  Implementation of the DRM Clock
*
*/


// INCLUDE FILES

#include <mmtsy_names.h>

#include "DRMClock.h"
#include "drmlog.h"
#include "DRMEventTimeChange.h"
#include "wmdrmfileserverclient.h"

#include <DRMNotifier.h>
#include <s32strm.h>
#include <s32file.h>
#include <e32property.h>
#include <e32keys.h>

#ifdef RD_MULTIPLE_DRIVE
#include <driveinfo.h>
#endif

#include "DRMNitzObserver.h"
#include "GPSWatcher.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES  

// CONSTANTS
const TInt KMinuteInMicroseconds = 60000000;
const TInt KTimeZoneIncrement = 15;
 
// The time zones sanity check values, not sure if -13 hours exists
// But atleast +13 does in: Nuku'Alofa
const TInt KTimeZoneLow = -52; // -13 hours
const TInt KTimeZoneHigh = 55; // +13 hours 45 minutes Some NZ owned island


// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

// FORWARD DECLARATIONS

// ============================= LOCAL FUNCTIONS ===============================


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


// -----------------------------------------------------------------------------
// CDRMRightsDB::CDRMRightsDB
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//    
CDRMClock::CDRMClock()
    {      
    };

// -----------------------------------------------------------------------------
// CDRMRightsDB::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CDRMClock::ConstructL()
    {
    DRMLOG( _L( "DRM Clock Starting: " ) );
    TInt error = KErrNone;

    // Create a notifier instance
    iNotifier = CDRMNotifier::NewL();
        
#ifndef __WINS__
    ConnectToPhoneL();            
            
    iObserver = CDRMNitzObserver::NewL( iPhone, const_cast<CDRMClock*>(this));

    iObserver->Start();
    
    TRAP( error, iGpsWatcher = CGPSWatcher::NewL( const_cast<CDRMClock*>(this) ));
    DRMLOG2( _L("DRMClock: GPS watcher started: %d"), error );    
#endif

    DRMLOG( _L( "DRM Clock started" ) );		    
    };

// -----------------------------------------------------------------------------
// CDRMClock::NewLC
// Two-phased constructor
// -----------------------------------------------------------------------------
//
CDRMClock* CDRMClock::NewLC()
    {
    DRMLOG( _L( "CDRMClock::NewLC" ) );
    
    CDRMClock* self = new(ELeave) CDRMClock;
    CleanupStack::PushL( self );
    self->ConstructL();
    
    DRMLOG( _L( "CDRMClock::NewLC ok" ) );
    
    return self;
    };

// -----------------------------------------------------------------------------
// CDRMClock::NewL
// Two-phased constructor
// -----------------------------------------------------------------------------
//
CDRMClock* CDRMClock::NewL()
    {
    DRMLOG( _L( "CDRMClock::NewL" ) );
    
    CDRMClock* self = NewLC();
    CleanupStack::Pop();

    DRMLOG( _L( "CDRMClock::NewL ok" ) );
    
    return self;
    };
  
// ---------------------------------------------------------
// CDRMClock::~CDRMClock
// Destructor
// ---------------------------------------------------------
//
CDRMClock::~CDRMClock()
    { 
    DRMLOG( _L( "CDRMClock::~CDRMClock" ) );
       
    if( iNotifier )
        {
        delete iNotifier;
        iNotifier = 0;
        }
        
#ifndef __WINS__
    if(iObserver)            
        {
        iObserver->Cancel();
        delete iObserver;
        iObserver = 0;
        }  
        
    if( iGpsWatcher )
        {
        iGpsWatcher->Cancel();
        delete iGpsWatcher;
        iGpsWatcher = 0;
        }   
#endif // __WINS__        
    };

// -----------------------------------------------------------------------------
// CDRMClock::GetSecureTime
// returns time and security level
// -----------------------------------------------------------------------------
//
void CDRMClock::GetSecureTime(TTime& aTime, TInt& aTimeZone, 
                              DRMClock::ESecurityLevel& aSecurityLevel)
    {
    DRMLOG( _L( "CDRMClock::GetSecureTime" ) );
    
    TTime currentUniversal;
    TTime currentHome;
    TInt error = KErrNone;
    
    // if there is an error it's not initialized
    error = aTime.UniversalTimeSecure();
    
    if( error == KErrNoSecureTime )
        {
        currentHome.HomeTime();               
        currentUniversal.UniversalTime();         
        
        aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / 
                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
        
        
        aTime.UniversalTime();

        aSecurityLevel = DRMClock::KInsecure; 
       
        DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Insecure" ) );        
        }
    else 
        {
        currentHome.HomeTimeSecure();        
        currentUniversal.UniversalTimeSecure();
        
        aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / 
                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
        
        aSecurityLevel = DRMClock::KSecure;     
        DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Secure" ) );  
        }    

    DRMLOG( _L( "CDRMClock::GetSecureTime ok" ) );
    };


// -----------------------------------------------------------------------------
// CDRMClock::ResetSecureTimeL
// resets the secure time and recalculates the offsets
// should not reset to 0
// -----------------------------------------------------------------------------
//
// Do not reset the timezone, use whatever has been set or retrieved from the UI time
// However check that the timezone is a valid one just in case
void CDRMClock::ResetSecureTimeL( const TTime& aTime, const TInt& aTimeZone )
    {
    DRMLOG( _L( "CDRMClock::ResetSecureTimeL" ) );
   
    TRequestStatus status;  
    TInt error = KErrNone;  
    CDRMEventTimeChange* change = CDRMEventTimeChange::NewLC();
	TTime previousTime;
	TTime previousTimeLocal;
	TTime newTime;
	TInt timezone = 0;
	TDateTime temppi; // Only for logging

    // check for param that the time is even reasonably valid:
    if( aTime.Int64() == 0 )
        {
        DRMLOG( _L("Trying to reset to zero time") );             
    	User::Leave( KErrArgument );
        }
    
    // Sanity check: Time zone has to be +/- certail hours
    // for this check -13h to +13.75h
    if( aTimeZone < KTimeZoneLow || aTimeZone > KTimeZoneHigh )
        {
        DRMLOG2( _L("TimeZone invalid, time may be as well, aborting change: %d"), aTimeZone  );
        User::Leave( KErrArgument );
        }
    
    
    // Get the current secure time with timezone
    // Ask the hometime first so that rounding of any divider goes correctly
    error = previousTimeLocal.HomeTimeSecure(); 
    
    // If there is an error, the secure hometime has not been set
    // Which means that the UI clock has the valid data
    if( error )
        {
        previousTimeLocal.HomeTime();
        previousTime.UniversalTime();
        timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / 
                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
		change->SetOldSecurityLevel( DRMClock::KInsecure );
		}
	else
		{
		previousTime.UniversalTimeSecure();		                   
        
        timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / 
                   ( KMinuteInMicroseconds* KTimeZoneIncrement );

		change->SetOldSecurityLevel( DRMClock::KSecure );
		change->SetNewSecurityLevel( DRMClock::KSecure );
		}
    
    // Since it's not important to get the timezone we keep what is set or reset it:
    previousTimeLocal = aTime.Int64() + ( timezone * ( KMinuteInMicroseconds* KTimeZoneIncrement ) );

    // Do the actual updating:
    // Update using the wmdrm fileserver since it has TCB capability
    RWmDrmFileServerClient resetclient;
    User::LeaveIfError( resetclient.Connect() );
    CleanupClosePushL( resetclient );
    
    newTime = aTime;
    User::LeaveIfError( resetclient.UpdateSecureTime( previousTimeLocal, newTime ) );
       
    CleanupStack::PopAndDestroy();


    DRMLOG( _L( "CDRMClock::ResetSecureTimeL: AFTER RESET." ));	

    // DRM Notifier data:
    // send info about the change:

    change->SetNewSecurityLevel( DRMClock::KSecure );
    
    change->SetOldTime( previousTime );
    change->SetOldTimeZone( timezone );

    change->SetNewTime( aTime );
    change->SetNewTimeZone( timezone );
    
    // Notify clients

    iNotifier->SendEventL(*change,status);
    User::WaitForRequest(status);
    CleanupStack::PopAndDestroy();    
    
    DRMLOG( _L( "CDRMClock::ResetSecureTimeL ok" ) );
    };

// ---------------------------------------------------------
// CDRMClock::Notify
// Notify DRM clock about an event
// ---------------------------------------------------------
//
void CDRMClock::Notify( TInt aNotify )
    {
    switch( aNotify )
        {
        case ENotifyGPSTimeReceived:
            // GPS time received, listen again after the next boot, destroy GPS watcher:
            DRMLOG(_L("Notify: ENotifyGPSTimeReceived, Deleting GPS watcher"));
            delete iGpsWatcher;
            iGpsWatcher = NULL;
            DRMLOG(_L("Notify: GPS Watcher deleted"));
            break;    
        case ENotifyNone:
        default:
            break;  // Do nothing    
        }    
    }





// ---------------------------------------------------------
// CDRMClock::ConnectToPhoneL(const TDateTime& aDateTime)
// Gets the nitz time from iNitzInfo
// ---------------------------------------------------------
//
void CDRMClock::ConnectToPhoneL()
    {
    DRMLOG( _L( "CDRMClock::ConnectToPhoneL" ) );
    
    const TInt KTriesToConnectServer(10);
    const TInt KTimeBeforeRetryingServerConnection(100000);
    TInt thisTry(0);
    TInt err(KErrNone);
    TInt numPhone;
    TName tsyName;
    RTelServer::TPhoneInfo phoneInfo;
    RMobilePhone::TMobilePhoneSubscriberId imsi;
    TRequestStatus status;
    

    while ((err = iEtelServer.Connect()) != KErrNone &&
                            (thisTry++) <= KTriesToConnectServer)
        {
        User::After(KTimeBeforeRetryingServerConnection);
        }
    User::LeaveIfError(err);

    User::LeaveIfError(iEtelServer.LoadPhoneModule(KMmTsyModuleName));
    User::LeaveIfError(iEtelServer.EnumeratePhones(numPhone));

    for (TInt i(0); i < numPhone; i++)
        {
        User::LeaveIfError(iEtelServer.GetPhoneInfo(i, phoneInfo));
        User::LeaveIfError(iEtelServer.GetTsyName(i,tsyName));

        if (tsyName.CompareF(KMmTsyModuleName) == 0)
            {
            break;
            }
        }

    User::LeaveIfError(iPhone.Open(iEtelServer, phoneInfo.iName));   
    
    iPhone.GetSubscriberId( status, imsi );
    User::WaitForRequest( status );
    
    DRMLOG( imsi );    
    DRMLOG( _L( "CDRMClock::ConnectToPhoneL ok" ) );
    };


// ========================== OTHER EXPORTED FUNCTIONS =========================


//  End of File