diff -r 000000000000 -r 4e1aa6a622a0 resourcemgmt/hwresourcesmgr/server/src/HWRMReservationHandler.cpp --- /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