--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp Tue Feb 02 01:56:55 2010 +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<CMMFAudioPolicyRequest>(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<CMMFAudioPolicyRequest>* 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);
+ }
+ }
+ }
+