diff -r 000000000000 -r bde4ae8d615e os/mm/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/mm/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,369 @@ +// Copyright (c) 2001-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 "MmfBtAudioPolicy.h" +#include "MmfBtAudioPolicySession.h" +#include "MmfBtAudioPolicyServer.h" +#include "MdaBtHwInfo.h" +#include "MmfBtAudioPolicyRequest.h" + +CAudioPolicy::~CAudioPolicy() + { + delete iMdaHwInfo; + delete iAudioPolicyRequestArray; + } + +void CAudioPolicy::ConstructL() + { + // Create dynamic array for sessions list + iAudioPolicyRequestArray = new(ELeave)CArrayFixFlat(CAudioPolicy::EGranularity); + iMdaHwInfo = CMdaHwInfo::NewL(); + } + +EXPORT_C CAudioPolicy* CAudioPolicy::NewL(CMMFAudioPolicyServer* aAudioPolicyServer) + { + + CAudioPolicy* self = new(ELeave)CAudioPolicy(aAudioPolicyServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return(self); + } + +CAudioPolicy::CAudioPolicy(CMMFAudioPolicyServer* aAudioPolicyServer) : + iAudioPolicyServer(aAudioPolicyServer) + { + } + +void CAudioPolicy::MakeRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest) + { + //Make sure there is sufficient space in the array to avoid expansion in AppendL() + __ASSERT_ALWAYS(iAudioPolicyRequestArray->Count() < iAudioPolicyServer->PolicySessionCount(), Panic(EMMFAudioPolicyRequestArrayOverflow)); + TPolicyResponse responseValue; + iSessionToAlert = NULL; // Reset + + // Process Request by looking at priorities, preferences, special states... + responseValue = ProcessRequest(aAudioPolicyRequest); + + // Finally, check current profile settings (only if not denied thus far): + // CheckAgainstProfiles(aAudioPolicyRequest, responseValue); + if (responseValue == EDenied) + { + SetSessionToAlert(aAudioPolicyRequest->PolicySessionId(), + NULL, TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow, + aAudioPolicyRequest->State()); + if(IsRegisteredNotification(aAudioPolicyRequest->PolicySessionId())) + { + TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) ); + __ASSERT_ALWAYS(err==KErrNone, Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this + } + } + + // If a client needs to be notified (either a previous session that was booted off or a new + // one that was denied) then send event for that session to the client: + // NB KErrInUse, KErrDied OR KErrAccessDenied may be used to indicate this. + if (iSessionToAlert != NULL) + { + //check the session is registered for notification of resource available + if(!IsRegisteredNotification(iSessionToAlert)) + { + RemoveFromList(iSessionToAlert); + } + iAudioPolicyEvent.iErrorCode = KErrInUse; + iAudioPolicyEvent.iState = aAudioPolicyRequest->State(); + iAudioPolicyServer->SendEventToClient(iSessionToAlert, iSessionToBeLaunched, iAudioPolicyEvent); + } + //Resume of a Audio of the notified client ,since it is already in the list + //no need to append and send response back to DevSound for request accepted. + if(responseValue == EResume) + { + iAudioPolicyServer->StopNotificationTimer(); + iAudioPolicyEvent.iErrorCode = KErrNone; + iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent; + iAudioPolicyEvent.iState = aAudioPolicyRequest->State(); + iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent); + } + // Add new policy to list, and send response back to DevSound for request accepted + if (responseValue == EProceed) + { + //no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession + TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) ); + __ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this + iAudioPolicyEvent.iErrorCode = KErrNone; + iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent; + iAudioPolicyEvent.iState = aAudioPolicyRequest->State(); + iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent); + } + if (responseValue == EStopThenProceed) // place on list, but dev Sound will launch request + { + //no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession + TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) ); + __ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this + } + } + +TPolicyResponse CAudioPolicy::ProcessRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest) + { + TPolicyResponse responseValue(EProceed); + iSessionToAlert = NULL; // Reset + + // If there is no other item on list, return with proceed + if (!iAudioPolicyRequestArray->Count()) + return EProceed; + + // Handle Preferences, if any, otherwise just compare priorities: + // HandlePreferences(aAudioPolicyRequest, preference, responseValue); + if(IsNotified()) + { + return EResume; + } + responseValue = ComparePriorities(aAudioPolicyRequest); + + return responseValue; + } + +void CAudioPolicy::ModifyEntry(TInt aPolicySessionId, CMMFAudioPolicyRequest* aAudioPolicyRequest) + { + TMMFAudioPolicyState requestState = aAudioPolicyRequest->State(); + // If state is stopped or paused, remove item from list + if ((aAudioPolicyRequest->State() == EMMFStatePaused) || (aAudioPolicyRequest->State() == EMMFStateStopped) || (aAudioPolicyRequest->State() == EMMFStateCompleted)) + { + if(iSessionToBeLaunched == aPolicySessionId) + { + iSessionToBeLaunched = 0; + } + if((aAudioPolicyRequest->State() == EMMFStateStopped) && (!iSessionToBeLaunched)) + { + TInt sessionToNotify = CheckSessionToNotify(); + if(sessionToNotify) + { + iAudioPolicyServer->StartNotificationTimer(); + iAudioPolicyEvent.iErrorCode = KErrNone; + iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification; + iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent); + } + } + if(aAudioPolicyRequest->NotificationEvent() != KMMFEventCategoryAudioResourceAvailable) + { + RemoveFromList(aPolicySessionId); + return; + } + } + + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + // Find correct entry to replace state + if ( ((*iAudioPolicyRequestArray)[index].PolicySessionId()) == aPolicySessionId) + { + (*iAudioPolicyRequestArray)[index].SetState(requestState); + break; + } + } + } + +void CAudioPolicy::RemoveFromList(TInt aPolicySessionId) + { + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + // Find correct entry to remove + if ( (*iAudioPolicyRequestArray)[index].PolicySessionId() == aPolicySessionId) + { + iAudioPolicyRequestArray->Delete(index); + break; + } + } + } + +TPolicyResponse CAudioPolicy::ComparePriorities(CMMFAudioPolicyRequest* aAudioPolicyRequest/*, TMMFAudioPolicyEvent& aEvent*/) + { + TPolicyResponse responseValue(EProceed); + TInt requestPriority = aAudioPolicyRequest->Priority(); + + TBool requestCaps = aAudioPolicyRequest->Capabilities(); + + // Iterate through list and compare priorities: + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + // If there's even one on the list w/ a higher priority deny request and leave: + + if ((*iAudioPolicyRequestArray)[index].Capabilities() > requestCaps) + { + responseValue = EDenied; + break; + } + else if((*iAudioPolicyRequestArray)[index].Capabilities() == requestCaps) + { + if((*iAudioPolicyRequestArray)[index].Priority() >= requestPriority) + { + responseValue = EDenied; + break; + } + } + + + // Otherwise have the one on the list removed: + SetSessionToAlert((*iAudioPolicyRequestArray)[index].PolicySessionId(), + aAudioPolicyRequest->PolicySessionId(), TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow, aAudioPolicyRequest->State()); + responseValue = EStopThenProceed; + } + return responseValue; + } + +void CAudioPolicy::HandlePreferences(CMMFAudioPolicyRequest* /*aAudioPolicyRequest*/, TInt /*aPref*/, TPolicyResponse& /*aResponse*/) + { + } + +void CAudioPolicy::LaunchRequest() + { + if (iAudioPolicyEventToLaunch.iEventType == TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle) + iAudioPolicyServer->LaunchRequest(iSessionToBeLaunched, iAudioPolicyEventToLaunch); + } + +// Sets up session information for sending an event on a denied (or killed) request +void CAudioPolicy::SetSessionToAlert(TInt aSessionToAlert, TInt aSessionToBeLaunched, TMMFAudioPolicyEvent::TAudioPolicyEventType aEventType, TMMFAudioPolicyState aState ) + { + iSessionToAlert = aSessionToAlert; + iSessionToBeLaunched = aSessionToBeLaunched; + iAudioPolicyEvent.iEventType = aEventType; + + if (iSessionToBeLaunched != 0) // When currently playing item needs to be stopped + { + iAudioPolicyEventToLaunch.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle; + iAudioPolicyEventToLaunch.iState = aState; + } + } + +CArrayFixFlat* CAudioPolicy::AudioPolicyRequestArray() + { + return iAudioPolicyRequestArray; + } + +/** +@internalTechnology + +This function raises a panic + +@param aError + one of the several panics codes that may be raised by this dll + +@panic EMMFAudioPolicyRequestArrayOverflow is raised when policyrequest array is full +*/ +GLDEF_C void Panic(TMMFAudioPolicyPanicCodes aPanicCode) + { + User::Panic(KMMFAudioPolicyPanicCategory, aPanicCode); + } + +// checks based on the session ,Is the session is registered for Notification +TBool CAudioPolicy::IsRegisteredNotification(TInt aSessionId) + { + TUid event; + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId) + { + event = (*iAudioPolicyRequestArray)[index].NotificationEvent(); + if (event == KMMFEventCategoryAudioResourceAvailable) + { + // only when the client is registered for KMMFEventCategoryAudioResourceAvailable event + return ETrue; + } + break; + } + } + return EFalse; + } + +// checks the state,whether any client is already send notification +TBool CAudioPolicy::IsNotified() + { + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified) + { + // In a instance only one client should have the state as EMMFStateNotified + return ETrue; + } + } + return EFalse; + } + +// get the next highest priority of the client to notify +TInt CAudioPolicy::CheckSessionToNotify() + { + TInt nextHighestPriority= -100; + TInt sessionToNotify = 0; + TInt notificationIdx = -1; + if(IsNotified()) + { + return sessionToNotify; + } + // get the max priority and set the Index + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + if((nextHighestPriority <= (*iAudioPolicyRequestArray)[index].Priority()) && ((*iAudioPolicyRequestArray)[index].NotificationEvent() != KNullUid) && (!(*iAudioPolicyRequestArray)[index].IsEventNotified())) + { + nextHighestPriority = (*iAudioPolicyRequestArray)[index].Priority(); + sessionToNotify = (*iAudioPolicyRequestArray)[index].PolicySessionId(); + notificationIdx = index; + } + } + // set the state as notified + if(notificationIdx != -1) + { + (*iAudioPolicyRequestArray)[notificationIdx].SetEventFlag(ETrue); + (*iAudioPolicyRequestArray)[notificationIdx].SetState(EMMFStateNotified); + } + return sessionToNotify; + } + +// send the message to the server +void CAudioPolicy::DoSendNotification() + { + ResetNotification(); + TInt sessionToNotify = CheckSessionToNotify(); + if(sessionToNotify) + { + iAudioPolicyEvent.iErrorCode = KErrNone; + iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification; + iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent); + } + } + +// Set in the AudiopolicyRequestArray the uid registered +TInt CAudioPolicy::SetNotification(TInt aSessionId, TUid aEventType) + { + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId) + { + (*iAudioPolicyRequestArray)[index].SetNotificationEvent(aEventType); + return ETrue; + } + } + return EFalse; + } + +// cancel the state of the message notification to closed +void CAudioPolicy::ResetNotification() + { + for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++) + { + if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified) + { + (*iAudioPolicyRequestArray)[index].SetState(EMMFStateClosed); + } + } + } +