--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/resourceman/resourcecontrol_extended.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,1188 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32\drivers\resourceman\resourcecontrol_extended.cpp
+//
+//
+
+#include <drivers/resourcecontrol.h>
+
+extern DPowerResourceController* PowerResourceController;
+/**
+@internalComponent
+@prototype 9.5
+
+Reserves the client level from pool to be used for updating resource client level in dependency resource.
+
+@param aCount Number of client levels to reserve from pool
+
+@return KErrNone On success
+@return KErrNoMemory Not enough memory to grow the pool
+*/
+TInt DPowerResourceController::ReserveClientLevelPoolCount(TUint16 aCount)
+ {
+ if(aCount < iResourceLevelPoolCount)
+ iResourceLevelPoolCount = (TUint16)(iResourceLevelPoolCount - aCount);
+ else
+ {
+ TUint allocCount = (iStaticResDependencyCount / 2) + aCount;
+ // coverity[alloc_fn]
+ SPowerResourceClientLevel* pCL = new SPowerResourceClientLevel[allocCount];
+ if(!pCL)
+ return KErrNoMemory;
+ for(TUint count = 0;count<(TUint)(allocCount);count++)
+ LIST_PUSH(iResourceLevelPool, &pCL[count], iNextInList);
+ iResourceLevelPoolCount= (TUint16)(iResourceLevelPoolCount + (iStaticResDependencyCount / 2));
+#ifdef PRM_INSTRUMENTATION_MACRO
+ TUint size = allocCount * sizeof(SPowerResourceClientLevel);
+ PRM_MEMORY_USAGE_TRACE
+#endif
+ }
+ return KErrNone;
+ }
+
+/**
+@internalComponent
+@prototype 9.5
+
+Return a client level object from pool.
+
+@param aLevelPtr Pointer to update the client level object.
+
+@return None
+*/
+void DPowerResourceController::RemoveClientLevelFromPool(SPowerResourceClientLevel *&aLevelPtr)
+ {
+ LIST_POP(iResourceLevelPool, aLevelPtr, iNextInList);
+ return;
+ }
+
+/**
+Update with number of dependent resources for the specified resource.
+*/
+TInt DPowerResourceController::GetNumDependentsForResource(TUint aResourceId, TUint* aNumResources)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetNumDependentsForResource"));
+
+ if(!(aResourceId & KIdMaskResourceWithDependencies))
+ return KErrNotSupported;
+ SNode* pN;
+ if(aResourceId & KIdMaskDynamic)
+ {
+ DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
+ if(!pDR)
+ return KErrNotFound;
+ pN = pDR->iDependencyList;
+ }
+ else
+ {
+ if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+ return KErrNotFound;
+ DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) - 1];
+ pN = pDR->iDependencyList;
+ }
+ *aNumResources = 0;
+ for(;pN != NULL; pN = pN->iNext)
+ (*aNumResources)++;
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetNumDependentsForResource"));
+ return KErrNone;
+ }
+
+/**
+Update the specified array with dependent resource Id's of the specified resource.
+*/
+TInt DPowerResourceController::GetDependentsIdForResource(TUint aResourceId, TAny* aInfo, TUint* aNumDepResources)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::GetDependentsIdForResource"));
+
+ if(!(aResourceId & KIdMaskResourceWithDependencies))
+ return KErrNotSupported;
+
+ if(!aInfo || !*aNumDepResources)
+ {
+ return KErrArgument;
+ }
+
+ TDes8 *pInfo = (TDes8*)aInfo;
+
+ if((TUint)(pInfo->MaxLength() - pInfo->Length()) < (sizeof(SResourceDependencyInfo)*(*aNumDepResources)))
+ return KErrArgument;
+
+ SResourceDependencyInfo sResDepInfo;
+
+ SNode* pN;
+ if(aResourceId & KIdMaskDynamic)
+ {
+ DDynamicPowerResourceD* pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
+ if(!pDR)
+ return KErrNotFound;
+ pN = pDR->iDependencyList;
+ }
+ else
+ {
+ if((aResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+ return KErrNotFound;
+ DStaticPowerResourceD* pDR = iStaticResDependencyArray[(TUint16)(aResourceId & ID_INDEX_BIT_MASK) -1];
+ pN = pDR->iDependencyList;
+ }
+ TUint count = 0;
+ TUint resCount = 0;
+
+ for(; pN != NULL; pN = pN->iNext)
+ {
+ resCount++;
+ if(count == *aNumDepResources)
+ continue;
+ sResDepInfo.iResourceId = pN->iResource->iResourceId;
+ sResDepInfo.iDependencyPriority = pN->iPriority;
+ pInfo->Append(TPckgC<SResourceDependencyInfo>(sResDepInfo));
+ }
+ *aNumDepResources = resCount;
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::GetDependentsIdForResource"));
+ return KErrNone;
+ }
+
+/**
+Registers resource dependency. This could be between 2 dynamic resource or between
+dynamic and static resource.
+*/
+TInt DPowerResourceController::RegisterResourceDependency(SPowerResourceClient* aClientPtr, SResourceDependencyInfo* aInfo1,
+ SResourceDependencyInfo* aInfo2)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterResourceDependency"));
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x",
+ aClientPtr->iClientId, aInfo1->iResourceId, aInfo2->iResourceId));
+
+ if(iDfcQDependencyLock)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
+ return KErrInUse;
+ }
+
+ TInt r = KErrNone;
+ //One of the resource must be dynamic resource
+ if(!(aInfo1->iResourceId & KIdMaskDynamic) && !(aInfo2->iResourceId & KIdMaskDynamic))
+ return KErrNotSupported;
+ //Both the resources should have dependency resource bit set in its id.
+ if(!(aInfo1->iResourceId & KIdMaskResourceWithDependencies) || !(aInfo2->iResourceId & KIdMaskResourceWithDependencies))
+ return KErrNotSupported;
+
+ DDynamicPowerResourceD* pR1 = NULL;
+ DDynamicPowerResourceD* pR2 = NULL;
+ SNode* pN1 = NULL;
+ SNode* pN2 = NULL;
+ //Retrieve resource1 from the corresponding list.
+ if(aInfo1->iResourceId & KIdMaskDynamic)
+ {
+ pR1 = iDynamicResDependencyList[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK)];
+ if(!pR1)
+ return KErrNotFound;
+ pN1 = pR1->iDependencyList;
+ }
+ else
+ {
+ if((aInfo1->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+ return KErrNotFound;
+ pR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo1->iResourceId & ID_INDEX_BIT_MASK) - 1];
+ pN1 = ((DStaticPowerResourceD*)pR1)->iDependencyList;
+ }
+ //Retrieve resource2 from the corresponding list.
+ if(aInfo2->iResourceId & KIdMaskDynamic)
+ {
+ pR2 = iDynamicResDependencyList[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK)];
+ if(!pR2)
+ return KErrNotFound;
+ pN2 = pR2->iDependencyList;
+ }
+ else
+ {
+ if((aInfo2->iResourceId & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+ return KErrNotFound;
+ pR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aInfo2->iResourceId & ID_INDEX_BIT_MASK) - 1];
+ pN2 = ((DStaticPowerResourceD*)pR2)->iDependencyList;
+ }
+
+ //Only long latency resource is allowed to have dependents.
+ if(!pR1->LatencySet())
+ pR1->iFlags |= KLongLatencySet;
+ if(!pR2->LatencySet())
+ pR2->iFlags |= KLongLatencySet;
+
+ //Check for closed loop
+ //NOTE: Panics, if any closed loop is encountered
+ if(pN1)
+ CheckForDependencyLoop((DStaticPowerResourceD*)pR1, pR1->iResourceId, pR2->iResourceId);
+
+ if(pN2)
+ CheckForDependencyLoop((DStaticPowerResourceD*)pR2, pR2->iResourceId, pR1->iResourceId);
+
+ //Check whether the passed priority already exists.Code will return with KErrAlreadyExists, if it exists.
+ CHECK_IF_PRIORITY_ALREADY_EXISTS(pN1, aInfo2->iDependencyPriority)
+ CHECK_IF_PRIORITY_ALREADY_EXISTS(pN2, aInfo1->iDependencyPriority)
+ UnLock();
+ //Allocate nodes
+ // coverity[alloc_fn]
+ SNode* pSN1 = new (SNode);
+ // coverity[alloc_fn]
+ SNode* pSN2 = new (SNode);
+ Lock();
+ if(!pSN1 || !pSN2)
+ return KErrNoMemory;
+ //Add the link
+ pSN1->iResource = (DStaticPowerResourceD*)pR1;
+ pSN1->iPropagatedLevel = 0;
+ pSN1->iPriority = aInfo1->iDependencyPriority;
+ pSN1->iVisited = EFalse;
+ pSN1->iNext = NULL;
+
+ pSN2->iResource = (DStaticPowerResourceD*)pR2;
+ pSN2->iPropagatedLevel = 0;
+ pSN2->iPriority = aInfo2->iDependencyPriority;
+ pSN2->iVisited = EFalse;
+ pSN2->iNext = NULL;
+
+ if(aInfo1->iResourceId & KIdMaskDynamic) //Dynamic resource
+ // coverity[memory_leak]
+ ADD_DEPENDENCY_NODE(pSN2, ((DDynamicPowerResourceD*)pR1)->iDependencyList)
+ else
+ ((DStaticPowerResourceD*)pR1)->AddNode(pSN2);
+
+ //Add the second node
+ if(aInfo2->iResourceId & KIdMaskDynamic) //Dynamic resource
+ // coverity[memory_leak]
+ ADD_DEPENDENCY_NODE(pSN1, ((DDynamicPowerResourceD*)pR2)->iDependencyList)
+ else
+ ((DStaticPowerResourceD*)pR2)->AddNode(pSN1);
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterResourceDependency"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+ PRM_REGISTER_RESOURCE_DEPENDENCY_TRACE
+#endif
+ return r;
+ }
+
+/**
+Registers dynamic resource.
+*/
+TInt DPowerResourceController::RegisterDynamicResource(SPowerResourceClient* aClientPtr, DDynamicPowerResource* aPDRes,
+ TUint* aDynamicResourceId)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::RegisterDynamicResource"));
+ TInt r = KErrNone;
+ //Check for dynamic resource
+ if(!(aPDRes->iResourceId & KIdMaskDynamic))
+ return KErrNotSupported;
+ //check for count
+ else if(aPDRes->LockCount() != 0)
+ return KErrAlreadyExists;
+
+ TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+ req->ReqType() = TPowerRequest::ERegisterDynamicResource;
+ req->Resource() = (DStaticPowerResource*)aPDRes;
+ UnLock();
+ req->SendReceive(iMsgQ);
+ Lock();
+ if(req->ReturnCode() == KErrNone)
+ {
+ *aDynamicResourceId = req->ResourceId();
+ aPDRes-> iOwnerId = aClientPtr->iClientId;
+ aPDRes->Lock();
+ //Increment dynamic resource count in client
+ aClientPtr->iDynamicResCount++;
+ }
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::RegisterDynamicResource, resource ID = 0x%x",
+ *aDynamicResourceId));
+#ifdef PRM_INSTRUMENTATION_MACRO
+ PRM_REGISTER_DYNAMIC_RESOURCE_TRACE
+#endif
+ return r;
+ }
+
+/**
+Deregisters dynamic resource.
+*/
+TInt DPowerResourceController::DeregisterDynamicResource(SPowerResourceClient* aClientPtr, TUint aResourceId,
+ TInt* aPDefLevel)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DExtendedResourceController::DeregisterDynamicResource"));
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("aClientId = 0x%x, aDynamicResourceId = 0x%x, Default Level = %d",
+ aClientPtr->iClientId, aResourceId, aPDefLevel ? *aPDefLevel : 0));
+ TInt r = KErrNone;
+ DDynamicPowerResource* pDR = NULL;
+ //Check for dynamic resource bit
+ if(!(aResourceId & KIdMaskDynamic))
+ return KErrNotSupported;
+
+ //Get the resource from appropriate container
+ if(aResourceId & KIdMaskResourceWithDependencies)
+ {
+ pDR = iDynamicResDependencyList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
+ if(!pDR)
+ return KErrNotFound;
+ }
+ else
+ {
+ pDR = iDynamicResourceList[(TUint16)(aResourceId & ID_INDEX_BIT_MASK)];
+ if(!pDR)
+ return KErrNotFound;
+ }
+ //Client which registered the dynamic resource is only allowed to deregister.
+ if(aClientPtr->iClientId != pDR->iOwnerId)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("Client attempting to deregister a dynamic resource which is not the owner!"));
+ return KErrAccessDenied;
+ }
+ // Don't allow to deregister if the some other operation is in progress or if the resource is shared and
+ // another client holds requirement on this resource
+ if((pDR->LockCount() > RESOURCE_NOT_IN_OPERATION) || pDR->InUse())
+ {
+ return KErrInUse;
+ }
+ TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+ req->ResourceCb() = NULL;
+ req->ReturnCode() = KErrNone;
+ req->RequiresChange() = EFalse;
+ pDR->UnLock(); //Marked as deleted so that no other operation will be taking place.
+ req->ReqType() = TPowerRequest::ESetDefaultLevel;
+ //Handle dynamic resource with dependencies
+ if(aResourceId & KIdMaskResourceWithDependencies)
+ {
+ for(SNode* pNode = ((DDynamicPowerResourceD*)pDR)->iDependencyList; pNode != NULL; pNode = pNode->iNext)
+ {
+ if((TUint)pNode->iResource->iLevelOwnerId == aResourceId)
+ {
+ req->ResourceId() = pNode->iResource->iResourceId;
+ req->ClientId() = aResourceId;
+ req->Level() = pNode->iResource->iCachedLevel;
+ req->Resource() = pNode->iResource;
+ ((DDynamicPowerResourceD*)(pNode->iResource))->Lock();
+ UnLock();
+ req->SendReceive(iMsgQDependency);
+ Lock();
+ }
+ //Remove entry from resource dependency list
+ for(SNode* pSN = pNode->iResource->iDependencyList; pSN != NULL; pSN = pSN->iNext)
+ {
+ if(pSN->iResource->iResourceId == aResourceId)
+ {
+ LIST_REMOVE(pNode->iResource->iDependencyList, pSN, iNext, SNode);
+ UnLock();
+ delete pSN;
+ Lock();
+ break;
+ }
+ }
+ //Remove from dependent resource "resource client level" list
+ for(SPowerResourceClientLevel* pL = ((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList;
+ pL != NULL; pL = pL->iNextInList)
+ {
+ if(pL->iClientId == aResourceId)
+ {
+ LIST_REMOVE(((DDynamicPowerResourceD*)(pNode->iResource))->iResourceClientList, pL, iNextInList,
+ SPowerResourceClientLevel);
+ //Move to free pool
+ LIST_PUSH(iResourceLevelPool, pL, iNextInList);
+ iResourceLevelPoolCount++;
+ }
+ }
+ ((DDynamicPowerResource*)(pNode->iResource))->UnLock();
+ }
+ //Move the resource to default level
+ req->ClientId() = -1;
+ req->ResourceId() = aResourceId;
+ req->Resource() = pDR;
+ if(aPDefLevel)
+ req->Level() = *aPDefLevel; //Set the resource to the passed level
+ else
+ req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
+ UnLock();
+ req->SendReceive(iMsgQDependency);
+ }
+ else
+ {
+ UnLock();
+ req->ResourceId() = aResourceId;
+ req->ClientId() = KDynamicResourceDeRegistering;
+ req->Resource() = pDR;
+ req->ResourceCb() = NULL;
+ if(aPDefLevel)
+ req->Level() = *aPDefLevel; //Set the resource to the passed level
+ else
+ req->Level() = pDR->iDefaultLevel; //Set the resource level to default level
+ if(pDR->LatencySet())
+ {
+ r = req->SendReceive(iMsgQ);
+ }
+ else
+ {
+ //Call custom function for custom sense resource
+ if(pDR->Sense() == DStaticPowerResource::ECustom)
+ {
+ if(!pDR->iCustomFunction)
+ Panic(ECustomFunctionNotSet);
+ pDR->iCustomFunction(req->ClientId(), *(aClientPtr->iName), aResourceId,
+ EDynamicResourceDeregister, req->Level(),
+ (TAny*)&pDR->iClientList, NULL);
+ }
+ //Not checking for error condition as the resource needs to be moved to default state
+ if(aPDefLevel)
+ {
+ //If the resource change to requested level fails trying to change it to default level.
+ req->ReqType() = TPowerRequest::EChange;
+ r = pDR->DoRequest(*req);
+ if(r != KErrNone)
+ {
+ req->ReqType() = TPowerRequest::ESetDefaultLevel;
+ req->Level() = pDR->iDefaultLevel;
+ pDR->DoRequest(*req);
+ }
+ }
+ else
+ pDR->DoRequest(*req);
+ //Send notifications. Passing -2 in clientId to indicate that this dynamic resource is deregistering
+ CompleteNotifications(KDynamicResourceDeRegistering, pDR, req->Level(),KErrNone, req->ClientId());
+ }
+ }
+ Lock();
+ //Remove client level
+ SPowerResourceClientLevel *pCL;
+ SPowerResourceClient *pC;
+ for(SDblQueLink* pRC = pDR->iClientList.First(); pRC != &pDR->iClientList.iA; pRC = pRC->iNext)
+ {
+ pCL = (SPowerResourceClientLevel*)pRC;
+ if(pCL->iClientId & USER_SIDE_CLIENT_BIT_MASK)
+ pC = iUserSideClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
+ else
+ pC = iClientList[(TUint16)(pCL->iClientId & ID_INDEX_BIT_MASK)];
+ LIST_REMOVE(pC->iLevelList, pCL, iNextInList, SPowerResourceClientLevel);
+ LIST_PUSH(iClientLevelPool, pCL, iNextInList);
+ if(pC->iUnderFlowClCount > 0)
+ {
+ pC->iUnderFlowClCount--;
+ iClientLevelPoolCount++;
+ }
+ else
+ pC->iReservedCl++;
+ }
+ //Decrement dynamic resource count in client
+ aClientPtr->iDynamicResCount--;
+ if(aResourceId & KIdMaskResourceWithDependencies)
+ {
+ iDynamicResDependencyList.Remove((DDynamicPowerResourceD*)pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
+ iDynamicResDependencyCount--;
+ }
+ else
+ {
+ iDynamicResourceList.Remove(pDR, (TUint16)(pDR->iResourceId & ID_INDEX_BIT_MASK));
+ iDynamicResourceCount--;
+ }
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DExtendedResourceController::DeregisterDynamicResource"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+ TInt level = req->Level();
+ PRM_DEREGISTER_DYNAMIC_RESOURCE_TRACE
+#endif
+ return r;
+ }
+
+/**
+@publishedPartner
+@prototype 9.6
+Default implementation, PSL re-implements this if features supported.
+*/
+TInt DPowerResourceController::DoRegisterStaticResourcesDependency(DStaticPowerResourceD**& aStaticResourceDArray,
+ TUint16& aStaticResourceDCount)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("DExtendedResourceController::DoRegisterStaticResourcesDependency default implementation"));
+ aStaticResourceDArray = NULL;
+ aStaticResourceDCount = 0;
+ return KErrNone;
+ }
+
+/**
+This function checks for any closed loop dependency, if so panics.
+*/
+void DPowerResourceController::CheckForDependencyLoop(DStaticPowerResourceD* pR, TUint aParentResId, TUint aTargetResId)
+ {
+ SNode *pN;
+
+ if(pR->iResourceId & KIdMaskDynamic)
+ pN = ((DDynamicPowerResourceD*)pR)->iDependencyList;
+ else
+ pN = pR->iDependencyList;
+
+ for(; pN != NULL; pN = pN->iNext)
+ {
+ if(pN->iResource->iResourceId == aParentResId)
+ continue;
+ if(pN->iVisited || (pN->iResource->iResourceId == aTargetResId))
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("Loop encountered\n"));
+ DPowerResourceController::Panic(DPowerResourceController::EClosedLoopDependencies);
+ }
+ pN->iVisited = ETrue;
+ CheckForDependencyLoop(pN->iResource, pR->iResourceId, aTargetResId);
+ pN->iVisited = EFalse;
+ }
+ }
+
+/**
+This is called from the controller thread to handle the dependency resource state change operation.
+*/
+TInt DPowerResourceController::HandleDependencyResourceStateChange(SPowerResourceClient* pC, TPowerRequest& aRequest)
+ {
+ DStaticPowerResourceD* pR = (DStaticPowerResourceD*)aRequest.Resource();
+ if(aRequest.ReqType() == TPowerRequest::EChange) //Handle resource change operation
+ {
+ if(aRequest.Resource()->Usage()) //Shared resource
+ {
+ Lock();
+ aRequest.ReturnCode() = CheckLevelAndAddClient(pC, &aRequest);
+ UnLock();
+ if((aRequest.ReturnCode()!= KErrNone) || (!aRequest.RequiresChange()))
+ {
+ aRequest.Level() = pR->iCachedLevel; //If no change then send the current level back.
+ return aRequest.ReturnCode();
+ }
+ }
+ else if(pR->iClientList.IsEmpty())
+ {
+ Lock();
+ if(pC->iReservedCl==0 && !iClientLevelPoolCount)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("Reserved Client Level exhausted and its free pool empty"));
+ aRequest.ReturnCode() = KErrUnderflow;
+ UNLOCK_RETURN(KErrUnderflow);
+ }
+ SPowerResourceClientLevel* pSCL=NULL;
+ LIST_POP(iClientLevelPool, pSCL, iNextInList);
+ pSCL->iClientId=pC->iClientId;
+ pSCL->iResourceId=aRequest.ResourceId();
+ pSCL->iLevel=aRequest.Level();
+ LIST_PUSH(pC->iLevelList, pSCL, iNextInList); //Add to client
+ pR->iClientList.Add(pSCL); //Add in resource
+ if(pC->iReservedCl==0)
+ {
+ iClientLevelPoolCount--;
+ pC->iUnderFlowClCount++;
+ }
+ else
+ pC->iReservedCl--;
+ if(pR->iCachedLevel == aRequest.Level())
+ {
+ pR->iLevelOwnerId = aRequest.ClientId();
+ if(pR->iIdleListEntry)
+ pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+ aRequest.ReturnCode() = KErrNone;
+ UNLOCK_RETURN(KErrNone);
+ }
+ UnLock();
+ }
+ else
+ {
+ //Update the level in the client list.
+ SPowerResourceClientLevel* pSCL = (SPowerResourceClientLevel*)pR->iClientList.First();
+ pSCL->iLevel = aRequest.Level();
+ }
+ //Call appropriate resource's handle change propagation function
+ if(pR->iResourceId & KIdMaskDynamic)
+ aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, pC->iClientId, *(pC->iName));
+ else
+ aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart,pC->iClientId, *(pC->iName));
+ return aRequest.ReturnCode();
+ }
+ if(aRequest.ClientId() == -1) //Special where the resource needs to set to default level, when dynamic resource deregisters
+ {
+ //If resource is asked to change to certain value, instead of default then
+ //try to set it to that value. If not able to set then try to set it to default level.
+ if(aRequest.Level() != pR->iDefaultLevel)
+ aRequest.ReqType() = TPowerRequest::EChange;
+ aRequest.ReturnCode() = pR->DoRequest(aRequest);
+ if((aRequest.ReturnCode() != KErrNone) && (aRequest.ReqType() == TPowerRequest::EChange))
+ {
+ aRequest.ReqType() = TPowerRequest::ESetDefaultLevel;
+ aRequest.Level() = pR->iDefaultLevel;
+ pR->DoRequest(aRequest);
+ }
+ //Set clientId to -2, indicating that the resource is deregistered.
+ CompleteNotifications(KDynamicResourceDeRegistering, pR, aRequest.Level(), KErrNone, aRequest.ClientId());
+ return KErrNone;
+ }
+ //Handle custom sense resource
+ if(aRequest.Resource()->Sense() == DStaticPowerResource::ECustom)
+ {
+ if(pR->iResourceId & KIdMaskDynamic)
+ {
+ aRequest.RequiresChange() = ((DDynamicPowerResourceD*)pR)->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(),
+ EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
+ (TAny*)&((DDynamicPowerResourceD*)pR)->iResourceClientList, NULL);
+ }
+ else
+ {
+ aRequest.RequiresChange() = pR->iDepCustomFunction(aRequest.ClientId(), *(pC->iName), aRequest.ResourceId(),
+ EClientRelinquishLevel, aRequest.Level(), (TAny*)&pR->iClientList,
+ (TAny*)&pR->iResourceClientList, NULL);
+ }
+ }
+ else
+ {
+ SPowerResourceClientLevel* pL = NULL;
+ SPowerResourceClientLevel* pMCL = NULL;
+ TInt maxLevel = KMinTInt;
+ //Find the maximum level from client
+ for(SDblQueLink* pCL = pR->iClientList.First(); pCL != &pR->iClientList.iA; pCL = pCL->iNext)
+ {
+ pL = (SPowerResourceClientLevel*)pCL;
+ if(pL->iClientId == (TUint)aRequest.ClientId())
+ continue;
+ if(pMCL == NULL)
+ {
+ maxLevel = pL->iLevel;
+ pMCL = pL;
+ continue;
+ }
+ if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
+ ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
+ {
+ maxLevel = pL->iLevel;
+ pMCL = pL;
+ }
+ }
+ //Find the maximum level from resource client level
+ if(pR->iResourceId & KIdMaskDynamic)
+ pL = ((DDynamicPowerResourceD*)pR)->iResourceClientList;
+ else
+ pL = pR->iResourceClientList;
+ for(; pL != NULL; pL = pL->iNextInList)
+ {
+ if(pL->iClientId == (TUint)aRequest.ClientId())
+ continue;
+ if(pMCL == NULL)
+ {
+ maxLevel = pL->iLevel;
+ pMCL = pL;
+ continue;
+ }
+ if(((pR->Sense() == DStaticPowerResource::ENegative) && (pL->iLevel < maxLevel)) ||
+ ((pR->Sense() == DStaticPowerResource::EPositive) && (pL->iLevel > maxLevel)))
+ {
+ maxLevel = pL->iLevel;
+ pMCL = pL;
+ }
+ }
+ if(pMCL == NULL)
+ {
+ aRequest.ClientId() = -1;
+ aRequest.Level() = pR->iDefaultLevel;
+ }
+ else
+ {
+ aRequest.ClientId() = pMCL->iClientId;
+ aRequest.Level() = maxLevel;
+ }
+ }
+ if((aRequest.Level() == pR->iCachedLevel) && !aRequest.RequiresChange()) //No need to change the resource just update the owner
+ {
+ pR->iLevelOwnerId = aRequest.ClientId();
+ if(pR->iIdleListEntry)
+ pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+ aRequest.ReturnCode() = KErrNone;
+ return KErrNone;
+ }
+ aRequest.ReqType() = TPowerRequest::EChange; //Make the change otherwise PSL set to default level
+
+ const TDesC8 *name;
+ if(aRequest.ClientId() == -1)
+ name = &KNoClient;
+ else
+ {
+ if(aRequest.ClientId() & (1 << RESOURCE_BIT_IN_ID_CHECK))
+ {
+ DStaticPowerResourceD* pResource;
+ if(aRequest.ClientId() & KIdMaskDynamic)
+ pResource = (DStaticPowerResourceD*)iDynamicResDependencyList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
+ else
+ pResource = iStaticResDependencyArray[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK) - 1];
+ name = pResource->iName;
+ }
+ else
+ {
+ SPowerResourceClient* pClient;
+ if(aRequest.ClientId() & USER_SIDE_CLIENT_BIT_MASK)
+ pClient = iUserSideClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
+ else // coverity[returned_null]
+ pClient = iClientList[(TUint16)(aRequest.ClientId() & ID_INDEX_BIT_MASK)];
+ name = pClient->iName;
+ }
+ }
+
+ if(pR->iResourceId & KIdMaskDynamic)
+ aRequest.ReturnCode() = ((DDynamicPowerResourceD*)pR)->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
+ else
+ aRequest.ReturnCode() = pR->HandleChangePropagation(aRequest, EChangeStart, aRequest.ClientId(), *name);
+ if(aRequest.ReturnCode() == KErrPermissionDenied) //Update the ownerId alone
+ {
+ pR->iLevelOwnerId = aRequest.ClientId();
+ if(pR->iIdleListEntry)
+ pR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+ }
+ return KErrNone;
+ }
+
+/**
+Deregisters resource dependency.
+*/
+TInt DPowerResourceController::DeregisterResourceDependency(SPowerResourceClient* aClientPtr, TUint aResId1, TUint aResId2)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::DeregisterResourceDependency"));
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("ClientId = 0x%x, ResourceId1 = 0x%x, ResourceId2 = 0x%x",
+ aClientPtr->iClientId, aResId1, aResId2));
+ if(iDfcQDependencyLock)
+ {
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf(">DPowerResourceController::RegisterResourceDependency::Resource In Use"));
+ UNLOCK_RETURN(KErrInUse);
+ }
+ DDynamicPowerResourceD *pDR1 = NULL;
+ DDynamicPowerResourceD *pDR2 = NULL;
+ SNode* pN1 = NULL;
+ SNode* pN2 = NULL;
+ SPowerResourceClientLevel* pCL1 = NULL;
+ SPowerResourceClientLevel* pCL2 = NULL;
+ //Get first resource from list
+ if(!(aResId1 & KIdMaskResourceWithDependencies) || !(aResId2 & KIdMaskResourceWithDependencies))
+ UNLOCK_RETURN(KErrAccessDenied);
+
+ if(aResId1 & KIdMaskDynamic)
+ {
+ pDR1 = iDynamicResDependencyList[(TUint16)(aResId1 & ID_INDEX_BIT_MASK)];
+ if(!pDR1)
+ UNLOCK_RETURN(KErrNotFound);
+ pN1 = pDR1->iDependencyList;
+ pCL1 = pDR1->iResourceClientList;
+ }
+ else
+ {
+ if((aResId1 & ID_INDEX_BIT_MASK) > iStaticResDependencyCount)
+ UNLOCK_RETURN(KErrNotFound);
+ pDR1 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(aResId1 & ID_INDEX_BIT_MASK) - 1];
+ pN1 = ((DStaticPowerResourceD*)pDR1)->iDependencyList;
+ pCL1 = ((DStaticPowerResourceD*)pDR1)->iResourceClientList;
+ }
+
+ //Get second resource from list
+ if(aResId2 & KIdMaskDynamic)
+ {
+ pDR2 = iDynamicResDependencyList[(TUint16)(aResId2 & ID_INDEX_BIT_MASK)];
+ if(!pDR2)
+ UNLOCK_RETURN(KErrNotFound);
+ pN2 = pDR2->iDependencyList;
+ pCL2 = pDR2->iResourceClientList;
+ }
+ else
+ {
+ if((aResId2 & ID_INDEX_BIT_MASK)> iStaticResDependencyCount)
+ UNLOCK_RETURN(KErrNotFound);
+ pDR2 = (DDynamicPowerResourceD*)iStaticResDependencyArray[(TUint16)(aResId2 & ID_INDEX_BIT_MASK) - 1];
+ pN2 = ((DStaticPowerResourceD*)pDR2)->iDependencyList;
+ pCL2 = ((DStaticPowerResourceD*)pDR2)->iResourceClientList;
+ }
+
+ //Check whether dependency exist between the two
+ SNode* pN = NULL;
+ for(pN = pN1; pN != NULL; pN = pN->iNext)
+ {
+ if(pN->iResource->iResourceId == pDR2->iResourceId)
+ break;
+ }
+ if(pN == NULL)
+ UNLOCK_RETURN(KErrNotFound);
+ pN1 = pN; //Storing for later use.
+ for(pN = pN2; pN != NULL; pN = pN->iNext)
+ {
+ if(pN->iResource->iResourceId == pDR1->iResourceId)
+ break;
+ }
+ if(pN == NULL)
+ return KErrNotFound;
+ pN2 = pN; //Storing for later use
+ //Remove the dependency link from both the resource
+ if(aResId1 & KIdMaskDynamic)
+ {
+ LIST_REMOVE(pDR1->iDependencyList, pN1, iNext, SNode);
+ }
+ else
+ {
+ LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iDependencyList, pN1, iNext, SNode);
+ }
+
+ if(aResId2 & KIdMaskDynamic)
+ {
+ LIST_REMOVE(pDR2->iDependencyList, pN2, iNext, SNode);
+ }
+ else
+ {
+ LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iDependencyList, pN2, iNext, SNode);
+ }
+
+ //Remove the resource client level from each resource
+ for(; pCL1 != NULL; pCL1 = pCL1->iNextInList)
+ {
+ if(pCL1->iClientId == pDR2->iResourceId)
+ {
+ if(aResId1 & KIdMaskDynamic)
+ {
+ LIST_REMOVE(pDR1->iResourceClientList, pCL1, iNextInList, SPowerResourceClientLevel);
+ }
+ else
+ {
+ LIST_REMOVE(((DStaticPowerResourceD*)pDR1)->iResourceClientList, pCL1, iNextInList,
+ SPowerResourceClientLevel);
+ }
+ LIST_PUSH(iResourceLevelPool, pCL1, iNextInList);
+ iResourceLevelPoolCount++;
+ break;
+ }
+ }
+ for(; pCL2 != NULL; pCL2 = pCL2->iNextInList)
+ {
+ if(pCL2->iClientId == pDR1->iResourceId)
+ {
+ if(aResId2 & KIdMaskDynamic)
+ {
+ LIST_REMOVE(pDR2->iResourceClientList, pCL2, iNextInList, SPowerResourceClientLevel);
+ }
+ else
+ {
+ LIST_REMOVE(((DStaticPowerResourceD*)pDR2)->iResourceClientList, pCL2, iNextInList,
+ SPowerResourceClientLevel);
+ }
+ LIST_PUSH(iResourceLevelPool, pCL2, iNextInList);
+ iResourceLevelPoolCount++;
+ break;
+ }
+ }
+
+ TPowerRequest* req = (TPowerRequest*)&TPowerRequest::Get();
+ req->ResourceCb() = NULL;
+ req->ReqType() = TPowerRequest::ESetDefaultLevel;
+ req->RequiresChange() = EFalse;
+ req->ReturnCode() = KErrNone;
+ if((TUint)pDR1->iLevelOwnerId == pDR2->iResourceId)
+ {
+ //Ask to change to default level. Process this in the RC thread;
+ req->ResourceId() = pDR1->iResourceId;
+ req->ClientId() = pDR2->iResourceId;
+ req->Resource() = pDR1;
+ req->Level() = pDR1->iDefaultLevel;
+ if(aResId1 & KIdMaskDynamic)
+ pDR1->Lock();
+ UnLock();
+ req->SendReceive(iMsgQDependency);
+ Lock();
+ if(aResId1 & KIdMaskDynamic)
+ pDR1->UnLock();
+ }
+ if((TUint)pDR2->iLevelOwnerId == pDR1->iResourceId)
+ {
+ //Ask to change to default level. Process this in the RC thread.
+ req->ResourceId() = pDR2->iResourceId;
+ req->ClientId() = pDR1->iResourceId;
+ req->Resource() = pDR2;
+ req->Level() = pDR2->iDefaultLevel;
+ if(aResId2 & KIdMaskDynamic)
+ pDR2->Lock();
+ UnLock();
+ req->SendReceive(iMsgQDependency);
+ Lock();
+ if(aResId2 & KIdMaskDynamic)
+ pDR2->UnLock();
+ }
+ __KTRACE_OPT(KRESMANAGER, Kern::Printf("<DPowerResourceController::DeregisterResourceDependency"));
+#ifdef PRM_INSTRUMENTATION_MACRO
+ PRM_DEREGISTER_RESOURCE_DEPENDENCY_TRACE
+#endif
+ UnLock();
+ delete pN1;
+ delete pN2;
+ return KErrNone;
+ }
+
+/**
+This function takes care of resource state change of static dependency resource.
+This propagates the change to all of its dependents.
+This function takes Originator name and id as parameter as this needs to be passed for custom sense function.
+*/
+TInt DStaticPowerResourceD::HandleChangePropagation(TPowerRequest aRequest, TPropagation aProp, TUint aOriginatorId, const TDesC8& aOriginatorName)
+ {
+ TInt result = KErrNone;
+ result = PowerResourceController->HandleResourceChange(aRequest, aProp, aOriginatorId, aOriginatorName, this);
+ return result;
+ }
+//Function to change the resource state of dependency resource.
+TInt DPowerResourceController::HandleResourceChange(TPowerRequest &aRequest, TPropagation aProp, TUint aOriginatorId,
+ const TDesC8& aOriginatorName, DStaticPowerResourceD* aResource)
+ {
+ static TUint16 clientLevelCount = 0;
+ DStaticPowerResourceD* pDR = (DStaticPowerResourceD*)aRequest.Resource();
+ DStaticPowerResourceD* pDepRes = NULL;
+ SNode* dependencyList = NULL;
+ TPowerRequest depRequest;
+ TInt result = KErrNone;
+ TInt resState;
+ depRequest.ReqType() = TPowerRequest::EChange;
+ depRequest.ResourceCb() = NULL;
+ depRequest.ReturnCode() = KErrNone;
+ depRequest.RequiresChange() = EFalse;
+
+ if(pDR->iResourceId & KIdMaskDynamic)
+ dependencyList = ((DDynamicPowerResourceD*)pDR)->iDependencyList;
+ else
+ dependencyList = pDR->iDependencyList;
+ switch(aProp)
+ {
+ case EChangeStart:
+ {
+ if(!dependencyList) /*No dependents so change state of the resource*/
+ {
+ aRequest.ReturnCode() = pDR->DoRequest(aRequest);
+ if(aRequest.ReturnCode() == KErrNone)
+ {
+ aResource->iCachedLevel = aRequest.Level();
+ aResource->iLevelOwnerId = aRequest.ClientId();
+ if(aResource->iIdleListEntry)
+ {
+ aResource->iIdleListEntry->iCurrentLevel = aRequest.Level();
+ aResource->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+ }
+ CompleteNotifications(aRequest.ClientId(), pDR,
+ aRequest.Level(), aRequest.ReturnCode(), aRequest.ClientId());
+ }
+ break;
+ }
+ depRequest.ResourceId() = aRequest.ResourceId();
+ depRequest.ClientId() = aRequest.ResourceId();
+ depRequest.Level() = aRequest.Level();
+ depRequest.Resource() = pDR;
+ result = pDR->HandleChangePropagation(depRequest, ECheckChangeAllowed, aOriginatorId, aOriginatorName);
+ if(result != KErrNone)
+ return result;
+ /*Adjust resource client level*/
+ if(clientLevelCount)
+ {
+ result = ReserveClientLevelPoolCount(clientLevelCount);
+ if(result != KErrNone)
+ return result;
+ }
+ /*Resource change of dependents */
+ pDR->HandleChangePropagation(aRequest, ERequestStateChange, aOriginatorId, aOriginatorName);
+ /*Notification to dependents */
+ pDR->HandleChangePropagation(aRequest, EIssueNotifications, aOriginatorId, aOriginatorName);
+ break;
+ }
+ case ECheckChangeAllowed:
+ {
+ TChangePropagationStatus status;
+ for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
+ {
+ pDepRes = depNode->iResource;
+ if((aRequest.ClientId() & KIdMaskResourceWithDependencies) &&
+ (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
+ continue;
+ /*Resource need not change if it is already in that state, so continue with
+ another dependent state.*/
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ status = ((DDynamicPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),
+ aRequest.Level(), resState);
+ else
+ status = ((DStaticPowerResourceD*)pDepRes)->TranslateDependentState(aRequest.ResourceId(),
+ aRequest.Level(), resState);
+ if((status == ENoChange) || (pDepRes->iCachedLevel == resState))
+ {
+ depNode->iRequiresChange = EFalse;
+ continue;
+ }
+ if(status == EChangeNotAccepted)
+ return KErrPermissionDenied;
+ depRequest.ResourceId() = pDepRes->iResourceId;
+ depRequest.ClientId() = aRequest.ResourceId(); /*ID of the dependent resource */
+ depRequest.Level() = resState;
+ depRequest.Resource() = pDepRes;
+ /*Check resource client list and resource list to see whether change is allowed.*/
+ if(pDepRes->Sense() == DStaticPowerResource::ECustom)
+ {
+ /*Call custom function to check whether change is allowed.*/
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ depRequest.RequiresChange() = ((DDynamicPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),
+ aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,
+ (TAny*)&((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, NULL);
+ else
+ depRequest.RequiresChange() = ((DStaticPowerResourceD*)pDepRes)->iDepCustomFunction(depRequest.ClientId(),
+ aOriginatorName, depRequest.ResourceId(), EClientRequestLevel, depRequest.Level(), (TAny*)&pDepRes->iClientList,
+ (TAny*)&((DStaticPowerResourceD*)pDepRes)->iResourceClientList, NULL);
+ if(!depRequest.RequiresChange())
+ return KErrPermissionDenied;
+ }
+ SPowerResourceClientLevel*pN=NULL;
+ for(SDblQueLink* pNL=pDepRes->iClientList.First();pNL!=&pDepRes->iClientList.iA; pNL=pNL->iNext)
+ {
+ pN = (SPowerResourceClientLevel*)pNL;
+ if(pDepRes->Sense() == DStaticPowerResource::EPositive)
+ {
+ if(pN->iLevel > depRequest.Level())
+ return KErrPermissionDenied;
+ }
+ else if(pDepRes->Sense() == DStaticPowerResource::ENegative)
+ {
+ if(pN->iLevel < depRequest.Level())
+ return KErrPermissionDenied;
+ }
+ }
+ /*check through the resource client level */
+ SPowerResourceClientLevel*pCL = NULL;
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;
+ else
+ pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;
+ for(; pCL != NULL; pCL = pCL->iNextInList)
+ {
+ if(pCL->iClientId == pDR->iResourceId)
+ break;
+ }
+ if(!pCL)
+ clientLevelCount++;
+ /*check dependent resource client list & resource list to see whether change is allowed */
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ result = ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,
+ ECheckChangeAllowed, aOriginatorId, aOriginatorName);
+ else
+ result = ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest,
+ ECheckChangeAllowed, aOriginatorId, aOriginatorName);
+ if(result != KErrNone)
+ return result;
+ depNode->iPropagatedLevel = resState;
+ depNode->iRequiresChange = ETrue;
+ }
+ break;
+ }
+ case ERequestStateChange:
+ {
+ SPowerResourceClientLevel* pCL = NULL;
+ for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
+ {
+ pDepRes = depNode->iResource;
+ if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
+ continue;
+ depRequest.ResourceId() = pDepRes->iResourceId;
+ depRequest.ClientId() = aRequest.ResourceId();
+ depRequest.Level() = depNode->iPropagatedLevel;
+ depRequest.Resource() = pDepRes;
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,
+ aOriginatorId, aOriginatorName);
+ else
+ ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, ERequestStateChange,
+ aOriginatorId, aOriginatorName);
+ /*Update level if resource client level is already present for this resource.*/
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ pCL = ((DDynamicPowerResourceD*)pDepRes)->iResourceClientList;
+ else
+ pCL = ((DStaticPowerResourceD*)pDepRes)->iResourceClientList;
+ for(; pCL != NULL; pCL = pCL->iNextInList)
+ {
+ if(pCL->iClientId == pDR->iResourceId)
+ {
+ pCL->iLevel = depNode->iPropagatedLevel;
+ break;
+ }
+ }
+ if(!pCL) /*Create a new resource client level*/
+ {
+ RemoveClientLevelFromPool(pCL);
+ pCL->iClientId = pDR->iResourceId;
+ pCL->iResourceId = pDepRes->iResourceId;
+ pCL->iLevel = depNode->iPropagatedLevel;
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ {
+ LIST_PUSH(((DDynamicPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);
+ }
+ else
+ {
+ LIST_PUSH(((DStaticPowerResourceD*)pDepRes)->iResourceClientList, pCL, iNextInList);
+ }
+ clientLevelCount--;
+ }
+ }
+#ifdef PRM_INSTRUMENTATION_MACRO
+ if(aRequest.ClientId() & KIdMaskResourceWithDependencies)
+ {
+ SPowerResourceClient res;
+ SPowerResourceClient* pC = &res;
+ pC->iClientId = aRequest.ClientId();
+ pC->iName = &KParentResource;
+ DStaticPowerResource*pR = (DStaticPowerResource*)pDR;
+ TUint aResourceId = pDR->iResourceId;
+ TInt aNewState = aRequest.Level();
+ PRM_CLIENT_CHANGE_STATE_START_TRACE
+ }
+#endif
+ aResource->DoRequest(aRequest);
+#ifdef PRM_INSTRUMENTATION_MACRO
+ if(aRequest.ClientId() & KIdMaskResourceWithDependencies)
+ {
+ SPowerResourceClient res;
+ SPowerResourceClient* pC = &res;
+ pC->iClientId = aRequest.ClientId();
+ pC->iName = &KParentResource;
+ DStaticPowerResource*pR = (DStaticPowerResource*)pDR;
+ TUint aResourceId = pDR->iResourceId;
+ TInt aNewState = aRequest.Level();
+ TInt r = KErrNone;
+ PRM_CLIENT_CHANGE_STATE_END_TRACE
+ }
+#endif
+ pDR->iCachedLevel = aRequest.Level();
+ pDR->iLevelOwnerId = aRequest.ClientId();
+ if(pDR->iIdleListEntry)
+ {
+ pDR->iIdleListEntry->iCurrentLevel = aRequest.Level();
+ pDR->iIdleListEntry->iLevelOwnerId = aRequest.ClientId();
+ }
+ break;
+ }
+ case EIssueNotifications:
+ {
+ for(SNode* depNode = dependencyList; depNode != NULL; depNode = depNode->iNext)
+ {
+ pDepRes = depNode->iResource;
+ if((!depNode->iRequiresChange) || (pDepRes->iResourceId == (TUint)aRequest.ClientId()))
+ continue;
+ depRequest.ResourceId() = pDepRes->iResourceId;
+ depRequest.ClientId() = pDepRes->iLevelOwnerId;
+ depRequest.Level() = pDepRes->iCachedLevel;
+ depRequest.Resource() = pDepRes;
+ if(pDepRes->iResourceId & KIdMaskDynamic)
+ ((DDynamicPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,
+ aOriginatorId, aOriginatorName);
+ else
+ ((DStaticPowerResourceD*)pDepRes)->HandleChangePropagation(depRequest, EIssueNotifications,
+ aOriginatorId, aOriginatorName);
+ }
+ CompleteNotifications(aRequest.ClientId(), pDR, aRequest.Level(), KErrNone,
+ aRequest.ClientId());
+ break;
+ }
+ default:
+ return KErrNotSupported;
+ }
+ return result;
+ }
+
+