resourcemgmt/hwresourcesmgr/server/src/HWRMReservationHandler.cpp
changeset 0 4e1aa6a622a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/resourcemgmt/hwresourcesmgr/server/src/HWRMReservationHandler.cpp	Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,526 @@
+// Copyright (c) 2006-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 "HWRMReservationHandler.h"
+#include "HWRMtrace.h"
+#include "HWRMClientServer.h" // panic ref
+#include "HWRMService.h"
+
+
+// EXTERNAL DATA STRUCTURES
+// None
+
+// EXTERNAL FUNCTION PROTOTYPES  
+// None
+
+// CONSTANTS
+// None
+
+// MACROS
+// None
+
+// LOCAL CONSTANTS AND MACROS
+_LIT( KPanicCategory, "HWRMReservationHandler" );
+
+// MODULE DATA STRUCTURES
+// None
+
+// LOCAL FUNCTION PROTOTYPES
+// None
+
+// FORWARD DECLARATIONS
+// None
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::CHWRMReservationHandler
+// C++ constructor
+// -----------------------------------------------------------------------------
+//
+CHWRMReservationHandler::CHWRMReservationHandler(TInt aSubResourceCount)
+    : iSubResourceCount(aSubResourceCount)
+    {
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::CHWRMReservationHandler()" ) );
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::CHWRMReservationHandler - return" ));
+    }
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHWRMReservationHandler* CHWRMReservationHandler::NewL(TInt aSubResourceCount, const TDesC& aPolicyFilename)
+    {
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::NewL(%d)" ), aSubResourceCount );
+
+    CHWRMReservationHandler* self = new( ELeave ) CHWRMReservationHandler(aSubResourceCount);
+    
+    CleanupStack::PushL( self );
+    
+    self->ConstructL(aPolicyFilename);
+    
+    CleanupStack::Pop();
+
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::NewL - return 0x%x" ), self );
+
+    return self;
+    }
+   
+// -----------------------------------------------------------------------------
+// CHWRMServer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHWRMReservationHandler::ConstructL(const TDesC& aPolicyFilename)
+    {
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::ConstructL()" ) );
+ 
+    // Initialize subtarget array with NULLS and create iAllMask
+    iAllMask = 0x0;
+    for ( TInt i=0; i < iSubResourceCount; i++ )
+        {
+        iReservations.AppendL(NULL);
+        
+        iAllMask <<= 1;  // initial shift is ignored as mask is zero on first loop
+        iAllMask |= 0x1;
+        }
+
+    // Initialize owned pointers
+    iPolicy = CHWRMPolicy::NewL(aPolicyFilename);
+    
+    // Consider all targets active by default
+    iActiveMask = iAllMask;
+
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::ConstructL - return" ) );
+    }   
+
+// ---------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------
+//
+CHWRMReservationHandler::~CHWRMReservationHandler()
+    {
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::~CHWRMReservationHandler()" ) );
+
+	delete iPolicy;
+	iPolicy = NULL;
+	
+    // destroy any reservations
+    for ( TInt i=0; i < iReservations.Count(); i++ )
+        {
+        while ( iReservations[i] )
+            {
+            TReservationData* deleteData = iReservations[i];
+            iReservations[i] = iReservations[i]->iSuspendedData;
+            delete deleteData;
+            }
+        }
+    iReservations.ResetAndDestroy();
+
+    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::~CHWRMReservationHandler - return" ) );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::ReserveL
+// Reserves resource
+// -----------------------------------------------------------------------------
+//
+TInt CHWRMReservationHandler::ReserveL(const RMessagePtr2& aMessage, TBool aForceNoCCoeEnv, CHWRMService* aServiceCallback, TInt aSubResourceMask)
+    {
+    COMPONENT_TRACE5(_L( "HWRM Server - CHWRMReservationHandler::ReserveL(0x%x, 0x%x, 0x%x, 0x%x)" ), aMessage.Handle(), aForceNoCCoeEnv, aServiceCallback, aSubResourceMask );
+
+    __ASSERT_ALWAYS(aServiceCallback, User::Panic(KPanicCategory, EPanicBadHandle));  
+
+    TBool trusted(EFalse);
+    TInt subMask(aSubResourceMask);  // Mask of subresources that caller wants to reserve
+    TInt reservedSuspendedMask(0x0); // Mask of subresources reserved in suspended mode
+    TInt alreadyReservedMask(0x0);   // Mask of subresources already reserved by this caller
+
+    // Get priority
+    TInt priority = iPolicy->GetPriority(aMessage.SecureId(), trusted);
+   
+    // If no CCoeEnv is forced, check that client is trusted
+    if ( aForceNoCCoeEnv && !trusted )
+        {
+        User::Leave(KErrAccessDenied);
+        }
+
+    // New reservation data(s) might be required for suspended reservations
+    // If multiple targets are suspended, datas create linked list
+    TReservationData* newDatas = NULL;
+    TInt newDataCount(0);
+
+    // If whole resource specified, use iAllMask
+    if ( aSubResourceMask == KHWRMAllSubResources)
+        {
+        subMask = iAllMask;
+        }
+
+    // Check reservations of all desired subtargets
+    TInt compareMask(0x1);
+    for ( TInt i=0; i < iSubResourceCount; i++ )
+        {
+        if ( (compareMask & subMask) )
+            {
+            TReservationData* reservationCheckData = iReservations[i];
+
+            // Check if caller is already reserving this subresource
+            while( reservationCheckData && !(alreadyReservedMask & compareMask) )
+                {
+                if ( reservationCheckData->iCallback == aServiceCallback )
+                    {
+                    alreadyReservedMask |= compareMask;
+                    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::ReserveL - Duplicate reservation for subresource 0x%x - Ignoring" ), compareMask );
+                    }
+                reservationCheckData = reservationCheckData->iSuspendedData;
+                }
+            
+            // If caller is not yet reserving this subresource, reserve it.
+            if ( !(alreadyReservedMask & compareMask) )
+                {
+                if ( iReservations[i] && iReservations[i]->iPriority <= priority )
+                    {
+                    // Add to reserve suspended mask
+                    reservedSuspendedMask |= compareMask;
+                    }
+
+                // Create data objects at this point so that any OOM leaves 
+                // will not cause reservation state to be uncertain
+                TReservationData* newOne = new (ELeave) TReservationData;
+                CleanupStack::PushL(newOne);
+                ++newDataCount;
+
+                if ( !newDatas )
+                    {
+                    newDatas = newOne;
+                    }
+                else
+                    {
+                    // There is already at least one newDatas, so link the new one up with old ones
+                    TReservationData* compareData = newDatas;
+                    while ( compareData->iSuspendedData )
+                        {
+                        compareData = compareData->iSuspendedData;	
+                        }
+                    compareData->iSuspendedData = newOne;
+                    }
+                }             
+            }
+            
+        compareMask <<= 1;
+        }
+
+    // Pop the TReservationData structures from the cleanup stack. This can be done here
+    // because no leaving functions are called in the following loop.
+    CleanupStack::Pop(newDataCount);
+
+    // Now we have done all memory allocations we need to, 
+    // so we can reserve specified subresources with no risk of OOM errors
+    // and therefore be sure that reservations array is never left in undetermined state.
+    compareMask = 0x1;
+    for ( TInt j=0; j < iSubResourceCount; j++ )
+        {
+        if ( (compareMask & subMask) && !(alreadyReservedMask & compareMask) )
+            {
+            // if things work right, this assert will never trigger
+            __ASSERT_ALWAYS(newDatas, User::Panic(KPanicCategory, EPanicBadHandle));  
+
+            TReservationData* nextData = newDatas->iSuspendedData;
+            newDatas->iCallback = aServiceCallback;
+            newDatas->iPriority = priority;
+            
+            if ( compareMask & reservedSuspendedMask )
+                {
+                // Reserve suspended, i.e. go through list until next one has lower priority
+                TReservationData* priorityCheckData = iReservations[j]->iSuspendedData;
+                TReservationData* priorityPreviousData = iReservations[j];
+                
+                while ( priorityCheckData 
+                        && priorityCheckData->iPriority <= priority )
+                    {
+                    priorityPreviousData = priorityCheckData;
+                    priorityCheckData = priorityCheckData->iSuspendedData;
+                    }
+                    
+                // insert new data
+                newDatas->iSuspendedData = priorityCheckData;
+                priorityPreviousData->iSuspendedData = newDatas;
+                }
+            else 
+                {
+                // Reserve as active, i.e. first in list
+                newDatas->iSuspendedData = iReservations[j];
+                iReservations[j] = newDatas;
+                
+                // Notify callback of current reserver, if any
+                if ( newDatas->iSuspendedData )
+                    {
+                    (newDatas->iSuspendedData->iCallback)->SuspendSubResource(j);
+                    }
+                }
+
+            newDatas = nextData; 
+            }
+            
+        compareMask <<= 1;
+        }
+
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::ReserveL - return: 0x%x" ), reservedSuspendedMask );
+    
+    return reservedSuspendedMask;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::Release
+// Releases resource
+// -----------------------------------------------------------------------------
+//
+TInt CHWRMReservationHandler::Release(CHWRMService* aServiceCallback, TInt aSubResourceMask)
+    {
+    COMPONENT_TRACE3(_L( "HWRM Server - CHWRMReservationHandler::Release(0x%x, 0x%x)" ), aServiceCallback, aSubResourceMask );
+
+    __ASSERT_ALWAYS(aServiceCallback, User::Panic(KPanicCategory, EPanicBadHandle));  
+
+    TInt unreservedMask(0x0);  // Return value, mask of all subresources that are unreserved.
+    TInt subMask(aSubResourceMask);    
+
+    // If whole resource specified, use iAllMask
+    if ( aSubResourceMask == KHWRMAllSubResources)
+        {
+        subMask = iAllMask;
+        }
+
+    // Check reservations of all desired subtargets
+    TInt compareMask(0x1);
+    for ( TInt i=0; i < iSubResourceCount; i++ )
+        {
+        if ( compareMask & subMask )
+            {
+            TReservationData* releasedService = NULL;
+            // Check if released client is active or suspended (or not reserved at all)
+            if ( iReservations[i] && iReservations[i]->iCallback == aServiceCallback )
+                {
+                // Released service was active, remove it
+                COMPONENT_TRACE3(_L( "HWRM Server - CHWRMReservationHandler::Release - Releasing: 0x%x, suspendedData = 0x%x" ), iReservations[i], iReservations[i]->iSuspendedData );
+                releasedService = iReservations[i];
+                iReservations[i] = iReservations[i]->iSuspendedData;
+                delete releasedService;
+                releasedService = NULL;
+                
+                // Reactivate first service on list if there still is one
+                if ( iReservations[i] && iReservations[i]->iCallback )
+                    {
+                    (iReservations[i]->iCallback)->ResumeSubResource(i);
+                    }
+                }
+            else if ( iReservations[i] )
+                {
+                // Released service is not active so it is either suspended or not reserved at all.
+                // Find the service from suspended services
+                TReservationData* checkData = iReservations[i]->iSuspendedData;
+                TReservationData* previousData = iReservations[i];
+                
+                while ( checkData && checkData->iCallback != aServiceCallback )
+                    {
+                    previousData = checkData;
+                    checkData = checkData->iSuspendedData;
+                    }
+                    
+                // Reset links and delete released service. 
+                // checkData is either NULL or the calling service at this point.
+                // If it is NULL, no need to delete anything, the service was not reserved.
+                if ( checkData )
+                    {                    
+                    COMPONENT_TRACE3(_L( "HWRM Server - CHWRMReservationHandler::Release - Releasing: 0x%x, suspendedData = 0x%x" ), checkData, checkData->iSuspendedData );                
+                    previousData->iSuspendedData = checkData->iSuspendedData;
+                    delete checkData;
+                    checkData = NULL;
+                    }
+                else
+                    {
+                    COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::Release - Reservation not found, releasing nothing" ) );                
+                    }
+                }
+            else
+                {
+                // Nothing reserved
+                }
+                
+            }
+
+        // update return value if no more reservations for this subresource
+        if ( !iReservations[i] )
+            {
+            unreservedMask |= compareMask;
+            }
+            
+        compareMask <<= 1;            
+        }
+
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::Release - return: 0x%x" ), unreservedMask );
+    
+    return unreservedMask;
+    }
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::IsReserved
+// -----------------------------------------------------------------------------
+//
+TBool CHWRMReservationHandler::IsReserved(const CHWRMService* aServiceCallback, TInt aSubResourceMask) const
+    {
+    COMPONENT_TRACE3(_L( "HWRM Server - CHWRMReservationHandler::IsReserved(0x%x, 0x%x)" ), aServiceCallback, aSubResourceMask );
+
+    __ASSERT_ALWAYS(aServiceCallback != NULL, User::Panic(KPanicCategory, EPanicBadHandle));  
+
+    TBool retval(EFalse);
+    TInt subMask(aSubResourceMask);    
+
+    // If whole resource specified, use iAllMask
+    if ( aSubResourceMask == KHWRMAllSubResources)
+        {
+        subMask = iAllMask;
+        }
+    
+    // Check if any of the specified subresources is reserved to somebody other than caller
+    TInt compareMask(0x1);
+    for ( TInt i=0; i < iSubResourceCount && !retval; i++ )
+        {
+        if ( (compareMask & subMask) && iReservations[i] && iReservations[i]->iCallback != aServiceCallback )
+            {            
+            retval = ETrue;
+            }
+            
+        compareMask <<= 1;            
+        }
+        
+
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::IsReserved - return: 0x%x" ), retval );
+    
+    return retval;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::GetUnreservedTargets
+// Returns target mask containing unreserved targets.
+// -----------------------------------------------------------------------------
+//
+TInt CHWRMReservationHandler::GetUnreservedTargets()
+    {
+    TInt compareMask(0x1);
+    TInt returnMask(0x0);
+    for ( TInt i=0; i < iSubResourceCount; i++ )
+        {
+        if ( !iReservations[i] )
+            {            
+            returnMask |= compareMask;
+            }
+            
+        compareMask <<= 1;            
+        }
+        
+    return returnMask;
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::UpdateActiveMask
+// Active targets mask indicates targets that are active (i.e. are not stripped
+// from target by target modifier plugin).
+// This is obviously not realtime information, but we are only interested in
+// targets that someone wants to modify anyway. I.e. if nobody wants to
+// adjust the state of some target after device state modification, we do not need
+// to know about it anyway. 
+// -----------------------------------------------------------------------------
+//
+void CHWRMReservationHandler::UpdateActiveMask(TInt aOriginalTarget, TInt aModifiedTarget, CHWRMService* aUpdater)
+    {
+    // All modified targets are activated
+    // All targets that were dropped from original target are deactivated.
+    TInt newActiveMask( (iActiveMask | aModifiedTarget) & ~(aOriginalTarget & ~aModifiedTarget) );
+    
+    COMPONENT_TRACE3(_L( "HWRM Server - CHWRMReservationHandler::UpdateActiveMask - Updated mask: 0x%x, old mask: 0x%x" ), newActiveMask, iActiveMask );
+
+    // Get bits that are different in old and new mask    
+    TInt differenceMask( iActiveMask ^ newActiveMask );
+    
+    iActiveMask = newActiveMask;
+
+    // Notify sessions with active reservation on modified targets
+    if ( differenceMask )
+        {
+        COMPONENT_TRACE1(_L( "HWRM Server - CHWRMReservationHandler::UpdateActiveMask - Notifying active sessions" ) );
+        TInt compareMask(0x1);
+        for ( TInt i=0; i < iSubResourceCount; i++ )
+            {
+            if ( compareMask & differenceMask )
+                {
+                TBool activate(compareMask & newActiveMask);
+                
+                // Skip activation notifications to whoever called this method as they are redundant.
+                // Deactivations are notified in any case.
+                if ( iReservations[i] && iReservations[i]->iCallback && (iReservations[i]->iCallback != aUpdater || !activate) )
+                    {
+                    (iReservations[i]->iCallback)->ActivateSubResource(i, activate);
+                    }
+                }
+                
+            compareMask <<= 1; 
+            }
+        }
+    
+    }
+    
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::GetActiveReserver
+// Returns active reserver for the specified target
+// -----------------------------------------------------------------------------
+//
+CHWRMService* CHWRMReservationHandler::GetActiveReserver(TInt aTarget)    
+    {
+    CHWRMService* retval = NULL;
+    
+    if ( iReservations[aTarget] )
+        {
+        retval = iReservations[aTarget]->iCallback;
+        }
+    
+    COMPONENT_TRACE2(_L( "HWRM Server - CHWRMReservationHandler::GetActiveReserver - return: 0x%x" ), retval );
+    return retval;
+    }
+
+// -----------------------------------------------------------------------------
+// CHWRMReservationHandler::GetPolicy
+// Returns policy instance
+// -----------------------------------------------------------------------------
+//
+CHWRMPolicy* CHWRMReservationHandler::GetPolicy()
+    {
+    return iPolicy;
+    }
+
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+//  End of File