omadrm/drmengine/server/src/drmconsume.cpp
changeset 0 95b198f216e5
child 18 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/server/src/drmconsume.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1138 @@
+/*
+* Copyright (c) 2005 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 class CDRMConsume.
+*
+*/
+
+
+// INCLUDE FILES
+#include "drmconsume.h"
+#include "drmenginetypedefs.h"
+#include "drmrightsdb.h"
+#include "drmrightsserver.h"
+#include "drmdbsession.h"
+#include "drmlog.h"
+#include "drmeventmodify.h"
+#include "drmnotifier.h"
+#ifdef RD_DRM_METERING
+#include "drmmeteringdb.h"
+#include "drmmeteringdbdata.h"
+#include "roapstorageclient.h"
+#include "drmricontext.h"
+#endif
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+// CONSTANTS
+// MACROS
+
+#define NOTIFIER static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+           iSession.Server() ) )->Notifier()
+
+#define DB static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+           iSession.Server() ) )->Database()
+           
+#define SECURETIME( a ) static_cast< CDRMRightsServer* >\
+           ( const_cast< CServer2* >( \
+           iSession.Server() ) )->GetSecureTime( a )
+           
+#define SERVER static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+           iSession.Server() ) )
+           
+#ifdef RD_DRM_METERING
+#define METERINGDB static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+           iSession.Server() ) )->MeteringDatabase() 
+#endif
+
+#define SETBIT( a, b ) ( a ) |= ( b )
+#define CLRBIT( a, b ) ( a ) &= ~( 0xff & b )
+#define ISSET( a, b ) ( ( a ) & ( b ) )
+
+// LOCAL CONSTANTS AND MACROS
+// Keeps track about modified permissions for UpdateDBL().
+//static const TUint8 KConsumeParentModified =   0x01;
+static const TUint8 KConsumeChildModified =    0x02;
+
+static const TUint8 KConsumeHasSecureTime =    0x08;
+
+// These keep track whether to decrease timed counters when consuming time
+// based stuff (iTimedCounts member). A used timed count bit is set to zero.
+// In the beginning all of these are set to one.
+//static const TUint8 KParentToplevelCount =     0x01;    
+//static const TUint8 KParentPermCount     =     0x02;
+static const TUint8 KChildToplevelCount  =     0x04;
+static const TUint8 KChildPermCount      =     0x08;
+
+static const TUint16 KConsumeDefaultTimer = 300; // 5mins
+
+// LOCAL FUNCTION PROTOTYPES
+static inline void PickSmaller( TTime& aFirst,
+                                const TTime& aSecond );
+
+// ============================= LOCAL FUNCTIONS ==========================
+
+// ------------------------------------------------------------------------
+// PickSmaller (overloaded)
+//
+// Set the smaller one to aFirst
+// ------------------------------------------------------------------------
+//
+void PickSmaller( TTime& aFirst,
+                  const TTime& aSecond )
+    {
+    if ( aSecond < aFirst )
+        {
+        aFirst = aSecond;
+        }
+    }
+    
+// ------------------------------------------------------------------------
+// PickSmaller (overloaded)
+//
+// Set the smaller one to aFirst
+// ------------------------------------------------------------------------
+//
+void PickSmaller( TTimeIntervalSeconds& aFirst,
+                  const TTimeIntervalSeconds& aSecond )
+    {
+    if ( aSecond < aFirst )
+        {
+        aFirst = aSecond;
+        }
+    }
+    
+// ============================ MEMBER FUNCTIONS ==========================
+
+// ------------------------------------------------------------------------
+// CDRMConsume::NewLC
+// ------------------------------------------------------------------------
+//
+CDRMConsume* CDRMConsume::NewLC( CDRMDbSession& aSession,
+                                 const TDesC8& aURI,
+                                 const TDesC8* aParentId )
+    {
+    DRMLOG( _L( "CDRMConsume::NewLC" ) );
+    CDRMConsume* self = new( ELeave ) CDRMConsume( aSession );
+    
+    CleanupStack::PushL( self );
+    
+    self->ConstructL( aURI, aParentId );
+    
+    DRMLOG( _L( "CDRMConsume::NewLC ok" ) );
+    return self;    
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::~CDRMConsume
+// ------------------------------------------------------------------------
+//
+CDRMConsume::~CDRMConsume()
+    {
+    DRMLOG( _L( "CDRMConsume::~" ) );
+    TInt error( KErrNone );
+    
+    if( IsActive() ) 
+        {
+        Cancel();        
+        }
+    else
+        {
+        TRAP( error, DoCancelL() );
+        }
+    #ifdef RD_DRM_METERING
+        // Update metering count and metering accumulated time to the database.
+        TRAP( error, UpdateMeteringDbL() );
+    #endif
+    // ignore errors
+    //TRAP( error, UpdateDBL() );
+    
+    delete iURI; iURI = NULL;
+    delete iParentId; iParentId = NULL;
+    delete iChild; iChild = NULL;
+    delete iCombined; iCombined = NULL;
+    DRMLOG( _L( "CDRMConsume::~ ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CDRMConsume
+//
+// The internal state members iTimedCounts and iCounters are by default
+// set to 00001111b, and the appropriate bits are lowered when something
+// changes.
+// ------------------------------------------------------------------------
+//
+CDRMConsume::CDRMConsume( CDRMDbSession& aSession ):
+    CTimer( EPriorityHigh ),
+    iSession( aSession ),
+    iIntent( ContentAccess::EUnknown ),
+    iURI( NULL ),
+    iParentId( NULL ),
+    iTimedCounts( 0xf ),
+    iCounters( 0xf ),
+    iCountConstraintActive( EFalse ),
+    iExpired( EFalse ),
+    iCumulativeDelayTop( 0 ),
+    iCumulativeDelayChild( 0 ),
+    iTotalCumulativeTime( 0 ),
+	iUsingTimedCount( 0 )
+    {
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::ConstructL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ConstructL( const TDesC8& aURI,
+                              const TDesC8* aParentId )
+    {
+    DRMLOG( _L( "CDRMConsume::ConstructL" ) );
+    CTimer::ConstructL();
+    iURI = aURI.AllocL();
+    if( aParentId )
+        {
+        iParentId = aParentId->AllocL();        
+        }
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::HandleL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::HandleL( ContentAccess::TIntent aIntent )
+    {
+    DRMLOG( _L( "CDRMConsume::HandleL" ) );
+    
+    TTime time;
+    TBool secure( SECURETIME( time ) );
+    InitializeL( aIntent, secure, time );
+    
+    DRMLOG( _L( "CDRMConsume::HandleL ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Pause
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Pause()
+    {
+    DRMLOG( _L( "CDRMConsume::Pause" ) );
+    
+    Cancel();
+    
+    DRMLOG( _L( "CDRMConsume::Pause ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: ContinueL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ContinueL()
+    {
+    DRMLOG( _L( "CDRMConsume::ContinueL" ) );
+    
+    Cancel();
+    
+    TInt error = KErrNone;
+    TUint32 reason = 0;
+                    
+    CDRMPermission* child = NULL;
+    HBufC8* parent = NULL;
+    
+    // This got removed by Pause()
+    if( iCountConstraintActive )
+        {
+        SERVER->AddActiveCountConstraintL( *iURI );
+        DoContinueL();
+        return;
+        }
+    
+    /* Fetch the RO again in order to manage a situation when another 
+       instance has used the same RO (content has been consumed) while the
+       other instance has not been used (player is paused) but will be 
+       used again (content consumption is to be continued). */   
+    error = iSession.FindRightsObject( iIntent, *iURI, child, parent, reason );
+    
+    /* Check if the RO found from the database matches with the one that was used
+       in the original consumption of the content. If the ROs match, use the
+       (possibly updated) one from the database. */
+    if ( !error && child && iChild && 
+         ( iChild->iUniqueID == child->iUniqueID ) &&
+         ( iChild->iOriginalInsertTime == child->iOriginalInsertTime ) )
+        {
+        if ( iParentId )
+            {
+            delete iParentId; 
+            iParentId = parent;
+            }
+            
+        delete iChild;
+        iChild = child;
+        }      
+    else 
+        {
+        /* The original RO was not found. Delete temporary objects and also
+           delete the iChild and iCombined because the RO is no longer valid and
+           need to be re-fetched using InitializeL method (in DoContinueL).   
+           (in DoContinueL). */  
+        if ( iChild )
+            {
+            delete iChild;
+            iChild = NULL;
+            }
+        
+        if ( iCombined )
+            {
+            delete iCombined;
+            iCombined = NULL;
+            }
+        
+        if ( child ) 
+            {
+            delete child;
+            child = NULL;
+            }
+        if ( parent )
+            {
+            delete parent;
+            parent = NULL;
+            }
+        } 
+          
+    DoContinueL();
+    
+    //HandleL( iIntent );
+    
+    DRMLOG( _L( "CDRMConsume::ContinueL ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Stop
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Stop()
+    {
+    DRMLOG( _L( "CDRMConsume::Stop" ) );
+    
+    Cancel();
+    
+    DRMLOG( _L( "CDRMConsume::Stop ok" ) );
+    }   
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: ActivateL
+//
+// Calculate the smallest end time based on interval, end time, 
+// accumulated time & timed count.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ActivateL( TBool aSecureTime,
+                             const TTime& aTrustedTime  )
+    {
+    DRMLOG( _L( "CDRMConsume::ActivateL" ) );
+    
+    __ASSERT_DEBUG( iChild && iCombined, User::Invariant() );
+    TTime endTime( Time::MaxTTime() );
+    TTimeIntervalSeconds timed( KMaxTInt32 );
+    TBool timeUsed( EFalse );
+    TBool endTimeUsed( EFalse );
+    
+    iCurrentDelay = 0;
+    
+    if ( iCombined->iActiveConstraints & EConstraintTimedCounter )
+        {
+        // Take this, even if timed counts have been updated. 
+        // This might cause unnecessary RunL's to be called, but it 
+        // ensures both child & parent will be consumed when needed.
+        // If e.g. it would be checked that iTimedCounts == 0xf, 
+        // either one (child or parent) might not get updated in case of
+        // "Child expired, but parent didn't -> find new child".        
+        PickSmaller( timed, iCombined->iTimedInterval );
+        timeUsed = ETrue;
+        }
+    
+    if ( iCombined->iActiveConstraints & EConstraintAccumulated )
+        {
+        PickSmaller( timed, iCombined->iAccumulatedTime );
+        timeUsed = ETrue;
+        }
+        
+    if ( iCombined->iActiveConstraints & EConstraintInterval )
+        {
+        if ( iCombined->iIntervalStart != Time::NullTTime() )
+            {
+            endTime = iCombined->iIntervalStart;
+            endTime += iCombined->iInterval;
+            endTimeUsed = ETrue;
+            }
+        else
+            {
+            TInt64 tmp( iCombined->iInterval.Int() );
+            
+            PickSmaller( timed, tmp );
+            timeUsed = ETrue;
+            }
+        }
+     
+    if ( iCombined->iActiveConstraints & EConstraintEndTime )
+        {
+        PickSmaller( endTime, iCombined->iEndTime );
+        endTimeUsed = ETrue;
+        }
+        
+    // Put the "smallest time" information to "endTime".
+    if ( timeUsed )
+        {
+        TTime current( aTrustedTime );
+        
+        current += timed;
+        
+        PickSmaller( endTime, current );
+        endTimeUsed = ETrue;
+        }
+        
+     // Interval gets initialised immediately, and so do count constraints.
+     // Timed/accumulated won't: those are consumed after the 
+     // interval if secure time exists.
+     Consume( ETrue, ETrue, EFalse, 0,
+              aSecureTime,
+              aTrustedTime );
+    
+     // In case something was modified, update the db also.
+     UpdateDBL();
+              
+     if ( endTimeUsed )
+        {     
+        // Something exists.
+        TTimeIntervalSeconds secs( 0 );
+        TTime current( aTrustedTime );
+        TInt err( KErrNone );
+        
+        // SecondsFrom returns an error if the difference is too great.
+        err = endTime.SecondsFrom( current, secs );
+        if ( err )
+            {
+            iCurrentDelay = KConsumeDefaultTimer;
+            }
+        else if ( secs.Int() < 0 )
+            {
+            iCurrentDelay = 0; // Already expired.
+            }
+        else if ( secs.Int() < KConsumeDefaultTimer )
+            {
+            iCurrentDelay = secs.Int();
+            }
+        else
+            {
+            iCurrentDelay = KConsumeDefaultTimer;
+            }
+           
+        if ( !IsAdded() )
+            {
+            CActiveScheduler::Add( this );
+            }
+        
+        DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ), 
+                  ( TInt )iCurrentDelay );
+                  
+        // secs -> microsecs. The method sets the AO active.
+        After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) );
+        
+        iTime = current;
+      
+        // If we see timed things here, we also have secure time.  
+        //SETBIT( iMask, KConsumeHasSecureTime );
+        }
+    else    // For metering we always need to have this:
+        {
+        iCurrentDelay = KConsumeDefaultTimer;
+        iTime = aTrustedTime;
+ 
+        if ( !IsAdded() )
+            {
+            CActiveScheduler::Add( this );
+            }
+                
+        DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ), 
+                  ( TInt )iCurrentDelay );
+                  
+        // secs -> microsecs. The method sets the AO active.
+        After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) );              
+        }    
+        
+    // If we see timed things here, we also have secure time.  
+    if( aTrustedTime != Time::NullTTime())
+        {
+        SETBIT( iMask, KConsumeHasSecureTime );        
+        }      
+    DRMLOG( _L( "CDRMConsume::ActivateL ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Consume
+//
+// Consume child & parent. Whether to consume parent's explicit
+// usage permission: the information is returned earlier by 
+// FindRightsObjectL.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Consume( TBool aUpdateCounter,
+                           TBool aInitInterval,
+                           TBool aUpdateTimedCount,
+                           const TTimeIntervalSeconds& aElapsedTime,
+                           TBool aSecureTime,
+                           const TTime& aTrustedTime )
+    {
+    DRMLOG( _L( "CDRMConsume::Consume" ) );
+    
+    __ASSERT_DEBUG( iChild && iCombined, User::Invariant() );
+    
+    // Decrease timed counters & regular counters only once.
+    // In the beginning the bitmasks are both 0xF.     
+    if ( iChild->TopLevelConstraint() )
+        {
+        if ( ConsumeConstraint( *( iChild->TopLevelConstraint() ),
+                                ( aUpdateCounter && 
+                                  ISSET( iCounters, KChildToplevelCount ) ),
+                                aInitInterval,
+                                ( aUpdateTimedCount && 
+                                  ISSET( iTimedCounts, 
+                                         KChildToplevelCount ) ),
+                                aElapsedTime,
+                                aSecureTime, 
+                                aTrustedTime,
+                                iCumulativeDelayTop ) )
+            {
+            SETBIT( iMask, KConsumeChildModified );
+            if ( aUpdateTimedCount )
+                {
+                CLRBIT( iTimedCounts, KChildToplevelCount );
+                }
+            if ( aUpdateCounter )
+                {
+                CLRBIT( iCounters, KChildToplevelCount );
+                }
+            }
+        }
+        
+    if ( ConsumeConstraint( *( iChild->ConstraintForIntent( iIntent ) ),
+                            ( aUpdateCounter && 
+                              ISSET( iCounters, KChildPermCount ) ),
+                            aInitInterval,
+                            ( aUpdateTimedCount && 
+                              ISSET( iTimedCounts, KChildPermCount ) ),
+                            aElapsedTime,
+                            aSecureTime,
+                            aTrustedTime,
+                            iCumulativeDelayChild ) )
+        {
+        SETBIT( iMask, KConsumeChildModified );
+        if ( aUpdateTimedCount )
+            {
+            CLRBIT( iTimedCounts, KChildPermCount );
+            }
+        if ( aUpdateCounter )
+            {
+            CLRBIT( iCounters, KChildPermCount );
+            }
+        }
+    
+    DRMLOG( _L( "CDRMConsume::Consume ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::RunL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::RunL()
+    {
+    DRMLOG2( _L( "CDRMConsume::RunL with %d" ), iStatus.Int() );
+    
+    switch ( iStatus.Int() )
+        {
+        case KErrNone:
+            // Normal completition.
+            
+        case KErrUnderflow:
+            // Time already passed.
+            
+        case KErrAbort:
+            // System time changed ==> consume.
+            DoContinueL();
+            break;
+
+        default:
+            // Some other (real) error.
+            // Handled in RunError.
+            User::Leave( iStatus.Int() );
+        };
+        
+    DRMLOG( _L( "CDRMConsume::RunL ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::RunError
+// ------------------------------------------------------------------------
+//
+#if defined( _DEBUG ) || defined( _LOGGING )
+TInt CDRMConsume::RunError( TInt aError )
+#else
+TInt CDRMConsume::RunError( TInt /* aError */ )
+#endif
+    {
+    DRMLOG2( _L( "CDRMConsume::RunError: %d" ), aError );
+     
+    Deque();
+    
+    DRMLOG( _L( "CDRMConsume::RunError ok" ) );
+    return 0;
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoCancel
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoCancel()
+    {
+    DRMLOG( _L( "CDRMConsume::DoCancel" ) );
+    
+    TInt error( KErrNone );
+    TRAP( error, DoCancelL() );
+    
+    DRMLOG2( _L( "CDRMConsume::DoCancel: %d" ), error );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoCancelL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoCancelL()
+    {
+    DRMLOG( _L( "CDRMConsume::DoCancelL" ) );
+    
+    if ( iCurrentDelay )
+        {
+        TTimeIntervalSeconds secs;
+        TTime trustedTime;
+        TBool secureTime;
+                        
+        CTimer::DoCancel();
+                
+        secureTime = SECURETIME( trustedTime );
+        trustedTime.SecondsFrom( iTime, secs );
+        
+        #ifdef RD_DRM_METERING
+            // Update total cumulative time for content metering purposes
+            iTotalCumulativeTime = iTotalCumulativeTime.Int() + secs.Int();
+        #endif
+             
+        // If the top level timed counter has not been activated yet
+        // increment the counter
+        if( ISSET( iTimedCounts, KChildToplevelCount ) )
+            {
+            iCumulativeDelayTop = iCumulativeDelayTop.Int() + secs.Int();            
+            }
+
+        // If the child timed counter has not been activated yet
+        // increment the counter            
+        if( ISSET( iTimedCounts, KChildPermCount ) )
+            {
+            iCumulativeDelayChild = iCumulativeDelayChild.Int() + secs.Int();
+            }
+            
+        // Always >= 0.
+        ConsumeTimedItemsL( secs,
+                            secureTime, 
+                            trustedTime );
+        iCurrentDelay = 0;
+        }
+    
+    UpdateDBL();
+    
+    if ( SERVER->HasActiveCountConstraint( *iURI ) )
+        {
+        SERVER->RemoveActiveCountConstraint( *iURI );
+        }
+    
+    DRMLOG( _L( "CDRMConsume::DoCancel ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CombinePermissionsL
+//
+// Combine iChild's & iParent's top level constraints, and merge the usage
+// intention constraint (either one of them).
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::CombinePermissionsL()
+    {
+    DRMLOG( _L( "CDRMConsume::CombinePermissions" ) );
+    
+    __ASSERT_DEBUG( iChild, User::Invariant() );
+    
+    // Reset
+    delete iCombined; iCombined = NULL;
+    iCombined = CDRMConstraint::NewL();
+    
+    if ( iChild->TopLevelConstraint() )
+        {
+        iCombined->Merge( *( iChild->TopLevelConstraint() ) );
+        }
+        
+    iCombined->Merge( *( iChild->ConstraintForIntent( iIntent ) ) );
+    
+    DRMLOG( _L( "CDRMConsume::CombinePermissions ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::UpdateDBL
+//
+// Update the DB if something was changed.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::UpdateDBL()
+    {
+    DRMLOG( _L( "CDRMConsume::UpdateDBL" ) );
+    // __ASSERT_DEBUG( iChild, User::Invariant() );
+        
+    CDRMEventModify* event = NULL;
+    TRequestStatus status;
+        
+    if( ISSET( iMask, KConsumeChildModified ) ) 
+        {
+        event = CDRMEventModify::NewL();
+        }
+    CleanupStack::PushL( event );    
+
+    if ( ISSET( iMask, KConsumeChildModified ) )
+        {
+        DRMLOG( _L( "CDRMConsume: commiting child to DB" ) );
+        
+        if( iParentId )
+            {
+            DB.UpdateDBEntryL( *iParentId, *iChild );
+            // Notify
+            event->SetContentIDL(*iParentId);
+            event->SetUniqueID(iChild->iUniqueID);
+            }
+        else
+            {
+            DB.UpdateDBEntryL( *iURI, *iChild );            
+            // Notify
+            event->SetContentIDL(*iURI);
+            event->SetUniqueID(iChild->iUniqueID);
+            }    
+        
+        // Notify
+        event->SetContentIDL(*iURI);
+        event->SetUniqueID(iChild->iUniqueID);
+        
+        NOTIFIER.SendEventL(*event,status);
+        User::WaitForRequest(status);           
+        
+        CLRBIT( iMask, KConsumeChildModified );
+        }
+    
+    CleanupStack::PopAndDestroy();    
+    DRMLOG( _L( "CDRMConsume::UpdateDBL ok" ) );
+    }
+// ------------------------------------------------------------------------
+// CDRMConsume::ConsumeConstraint
+//
+// Consume child & parent. Whether to consume parent's explicit
+// usage permission: the information is returned earlier by 
+// FindRightsObjectL.
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::ConsumeConstraint( CDRMConstraint& aConstraint,
+                                      TBool aUpdateCounter,
+                                      TBool aInitInterval,
+                                      TBool aUpdateTimedCount,
+                                      const TTimeIntervalSeconds& aElapsedTime,
+                                      TBool aSecureTime,
+                                      const TTime& aTrustedTime,
+                                      TTimeIntervalSeconds& aCumulativeTime )
+    {
+    DRMLOG( _L( "CDRMConsume::ConsumeConstraints" ) );
+    
+    TBool res( EFalse );
+    
+    if ( aUpdateCounter && 
+         ( aConstraint.iActiveConstraints & EConstraintCounter ) )
+        {
+        --( aConstraint.iCounter);
+        res = ETrue;
+        iCountConstraintActive = ETrue;
+        TRAP_IGNORE( SERVER->AddActiveCountConstraintL( *iURI ) ); 
+        }
+        
+    if ( aInitInterval &&
+         ( aConstraint.iActiveConstraints & EConstraintInterval ) &&
+         aSecureTime &&
+         aConstraint.iIntervalStart == Time::NullTTime() )
+        {
+        aConstraint.iIntervalStart = aTrustedTime;
+        res = ETrue;
+        }
+        
+    /* change to timed counter, we don't check the latest time, we check the
+    cumulated time */    
+        
+    if ( aUpdateTimedCount &&
+         ( aConstraint.iActiveConstraints & EConstraintTimedCounter &&
+           ( aCumulativeTime >= aConstraint.iTimedInterval ||
+             aElapsedTime >= aConstraint.iTimedInterval  ) ) )
+        {
+        --( aConstraint.iTimedCounter );
+        res = ETrue;
+        iCountConstraintActive = ETrue;
+        TRAP_IGNORE( SERVER->AddActiveCountConstraintL( *iURI ) ); 
+        aCumulativeTime = TTimeIntervalSeconds( 0 );
+        }
+    else if ( aUpdateTimedCount &&
+         ( aConstraint.iActiveConstraints & EConstraintTimedCounter ) )
+        {
+        iUsingTimedCount = ETrue;
+        }
+        
+    
+    if ( aElapsedTime.Int() != 0 &&
+         ( aConstraint.iActiveConstraints & EConstraintAccumulated ) )
+        {
+        __ASSERT_DEBUG( aElapsedTime.Int() > 0, User::Invariant() );
+        
+        if ( aConstraint.iAccumulatedTime < aElapsedTime )
+            {
+            aConstraint.iAccumulatedTime = 0;
+            }
+        else
+            {
+            aConstraint.iAccumulatedTime = aConstraint.iAccumulatedTime.Int() - 
+            	aElapsedTime.Int();
+            }
+        
+        res = ETrue;
+        }
+        
+    if ( !iCountConstraintActive && aConstraint.Expired( aTrustedTime ) )
+        {
+        iExpired = ETrue;
+        }
+    else
+        {
+        iExpired = EFalse;
+        }
+    
+    DRMLOG2( 
+        _L( "CDRMConsume::ConsumeConstraints ok, returning %d" ), 
+        ( TInt )res );
+        
+    return res;
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::ConsumeTimedItemsL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ConsumeTimedItemsL( TTimeIntervalSeconds aDelay,
+                                      TBool aSecureTime,
+                                      const TTime& aTrustedTime )
+    {
+    DRMLOG( _L( "CDRMConsume::ConsumeTimedItemsL" ) );
+    
+    // Update accumulated constraints & timed count.
+    Consume( EFalse,
+             ETrue,
+             ETrue,
+             aDelay,
+             aSecureTime,
+             aTrustedTime );
+    
+    DRMLOG( _L( "CDRMConsume::ConsumeTimedItems ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoContinueL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoContinueL()
+    {
+    DRMLOG( _L( "CDRMConsume::DoContinueL" ) );
+    
+    TTime time;
+    TBool secureTime( EFalse );
+    secureTime = SECURETIME( time );
+    
+    if ( !iChild || !iCombined )
+        {
+        InitializeL( iIntent, secureTime, time );
+        // User::Leave( KErrCANoRights );
+        return;
+        }
+   
+    ConsumeTimedItemsL( iCurrentDelay, secureTime, time );
+    UpdateDBL();
+    iCurrentDelay = 0;
+    
+    CombinePermissionsL();
+    
+    // If the content has expired, find new permissions, unless the expired
+    // constraint was a timed count. In that case, the constraint
+    // did not really expire.
+    if ( SecurityLevelChanged( secureTime ) ||
+         ( iCombined->Expired( time ) && 
+           !SERVER->HasActiveCountConstraint( *iURI ) ) )
+        {
+        InitializeL( iIntent, secureTime, time );
+        }
+    else
+        {
+        ActivateL( secureTime, time );
+        }
+        
+    DRMLOG( _L( "CDRMConsume::DoContinueL ok" ) );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::SecurityLevelChanged
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::SecurityLevelChanged( TBool aSecureTime ) const
+    {
+    DRMLOG( _L( "CDRMConsume::SecurityLevelChanged" ) );
+    
+    if ( ( ISSET( iMask, KConsumeHasSecureTime ) && aSecureTime ) ||
+         !( ISSET( iMask, KConsumeHasSecureTime ) || aSecureTime ) )
+        {
+        return EFalse;
+        }
+        
+    return ETrue;
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::InitializeL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::InitializeL( ContentAccess::TIntent aIntent,
+                               TBool aSecureTime,
+                               const TTime& aTrustedTime )
+    {
+    DRMLOG( _L( "CDRMConsume::InitializeL" ) );
+    
+    // aIntent is either EPlay, EView, EExecute or EPrint.
+    // Store the old  consumption information in case this is 
+    // called in case of "ran out of permissions, find new ones"
+    CDRMPermission* child( iChild );
+    TUint8 timedCounts( iTimedCounts );
+    TUint8 counters( iCounters );
+    TUint32 reason = 0;
+    
+    // Reset.
+    iTimedCounts = 0xf;
+    iCounters = 0xf;
+    iMask = 0x0;
+    iCurrentDelay = 0;
+    
+    iExpired = ETrue;
+    
+    delete iCombined; iCombined = NULL;
+    
+    // Previous child & parent need to be stored in case the internal 
+    // counter states need to be restored.
+    if ( child )
+        {
+        CleanupStack::PushL( child );
+        iChild = NULL;
+        }
+    
+    // If the next call won't leave, we have permissions.
+    User::LeaveIfError( iSession.FindRightsObject( aIntent, 
+                                                   *iURI,
+                                                   iChild,
+                                                   iParentId,
+                                                   reason ) );
+                                
+    User::LeaveIfError( iSession.VerifyCredentials( iURI, iChild, aIntent ) );
+                                
+    iExpired = EFalse;
+
+    // Check whether to restore the internal state.
+    if ( iIntent == aIntent ) 
+        {
+        if ( child && 
+             ( child->iUniqueID == iChild->iUniqueID ) )
+            {
+            DRMLOG( _L( "CDRMConsume: using the previous child" ) );
+            
+            CLRBIT( iTimedCounts, 
+                    ( KChildToplevelCount | KChildPermCount ) & ~timedCounts );
+                    
+            CLRBIT( iCounters,
+                    ( KChildToplevelCount | KChildPermCount ) & ~counters );
+            }
+        }
+    
+    if ( child )
+        {
+        CleanupStack::PopAndDestroy();
+        }
+    
+    iIntent = aIntent;
+    
+    CombinePermissionsL();
+    ActivateL( aSecureTime, aTrustedTime );
+
+    DRMLOG( _L( "CDRMConsume::InitializeL ok" ) );
+    }
+    
+// ------------------------------------------------------------------------
+// CDRMConsume::CountConstraintActive
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::CountConstraintActive()
+    {
+    return iCountConstraintActive || SERVER->HasActiveCountConstraint( *iURI );
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::IsExpired
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::IsExpired()
+    {
+    return iExpired;
+    }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::GetChild
+// ------------------------------------------------------------------------
+//
+CDRMPermission& CDRMConsume::GetChild()
+    {
+    return *iChild;
+    }
+
+#ifdef RD_DRM_METERING
+
+// ------------------------------------------------------------------------
+// CDRMConsume::UpdateMeteringDbL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::UpdateMeteringDbL()
+    {
+    DRMLOG( _L( "CDRMConsume::UpdateMeteringDbL" ) ); 
+    TTimeIntervalSeconds graceTime = 0;
+    CDRMConstraint* constraint = NULL;
+             
+    if ( iChild )
+        {
+        constraint = iChild->ConstraintForIntent( iIntent ); 
+        if ( constraint && constraint->iDrmMeteringInfo )  
+            { 
+            
+            graceTime = constraint->iDrmMeteringInfo->iGraceTime;
+            
+            // Grace time exceeded, increase metering count and metering 
+            // accumulated time    
+            if ( iTotalCumulativeTime >= graceTime )  
+                {
+                // Check Rights Issuer rights from Roap storage
+                if ( !CheckRiContextRightsL( iChild->iRiId ) )    
+                    {
+                    return;
+                    }
+                
+                // Update database only if Rights Issuer Id is available
+                if ( ( iChild->iRiId.Length() > 0 ) && 
+                     ( iChild->iRiId.Length() <= KRiIdSize ) ) 
+                    {
+                    
+                    if ( iURI )
+                        {
+                        CDrmMeteringDbData* meteringData = 
+                            CDrmMeteringDbData::NewLC();
+                        meteringData->iContentId = iURI->AllocL();
+                        meteringData->iRiId = iChild->iRiId; 
+                        if( iUsingTimedCount && !iCountConstraintActive ) 
+                            {
+                            meteringData->iCount = 0;                            
+                            }
+                        else
+                            {
+                        meteringData->iCount = 1;
+                            }
+                            
+                        meteringData->iAccumulatedTime = iTotalCumulativeTime;
+                        
+                        if ( iParentId ) 
+                            {
+                            meteringData->iParentUid = iParentId->AllocL();
+                            }
+                 
+                        METERINGDB.AddL( meteringData );
+                        CleanupStack::PopAndDestroy(); // meteringData
+                        }            
+                    }
+                } 
+            }             
+        }
+        DRMLOG( _L( "CDRMConsume::UpdateMeteringDbL ok" ) );
+    }
+    
+// ------------------------------------------------------------------------
+// CDRMConsume::CheckRiContextRightsL
+// ------------------------------------------------------------------------
+//
+
+TBool CDRMConsume::CheckRiContextRightsL( const TDesC8& aRiId )
+    {
+    
+    DRMLOG( _L( "CDRMConsume::CheckRiContextRightsL" ) );
+    
+    CDRMRIContext* riContext = NULL;
+    TBool haveRights = EFalse; 
+  
+    // Connect to the storage of the registered Rights Issuers 
+    
+    if( iSession.ConnectRoapClient() == KErrNone )
+        {
+    riContext = iSession.RoapClient().GetRIContextL( aRiId );
+     
+    if ( riContext == NULL )
+        {
+        DRMLOG( _L ( "RI not registered" ) );
+        User::Leave( KErrRightsServerRiNotRegistered );
+        }
+        
+    // Check (via the Rights Issuer context) whether Rights Issuer 
+    // is allowed to use metering or not
+    if ( riContext->IsMeteringAllowed() )
+        {
+        haveRights = ETrue;
+        }
+        
+    if ( riContext ) 
+        {
+        delete riContext;
+        riContext = NULL;    
+        }
+        }
+        
+    return haveRights;
+    
+    }
+
+#endif
+
+// EOF