os/mm/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/mm/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,369 @@
     1.4 +// Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +#include "MmfBtAudioPolicy.h"
    1.20 +#include "MmfBtAudioPolicySession.h"	
    1.21 +#include "MmfBtAudioPolicyServer.h"
    1.22 +#include "MdaBtHwInfo.h"	
    1.23 +#include "MmfBtAudioPolicyRequest.h"
    1.24 +
    1.25 +CAudioPolicy::~CAudioPolicy()
    1.26 +	{
    1.27 +	delete iMdaHwInfo;
    1.28 +	delete iAudioPolicyRequestArray; 		
    1.29 +	}
    1.30 +
    1.31 +void CAudioPolicy::ConstructL()
    1.32 +	{
    1.33 +	// Create dynamic array for sessions list
    1.34 +	iAudioPolicyRequestArray = new(ELeave)CArrayFixFlat<CMMFAudioPolicyRequest>(CAudioPolicy::EGranularity);
    1.35 +	iMdaHwInfo = CMdaHwInfo::NewL();
    1.36 +	}
    1.37 +
    1.38 +EXPORT_C CAudioPolicy* CAudioPolicy::NewL(CMMFAudioPolicyServer* aAudioPolicyServer)
    1.39 +	{	
    1.40 +
    1.41 +	CAudioPolicy* self = new(ELeave)CAudioPolicy(aAudioPolicyServer);
    1.42 +	CleanupStack::PushL(self);
    1.43 +	self->ConstructL();
    1.44 +	CleanupStack::Pop();
    1.45 +	return(self);
    1.46 +	}
    1.47 +
    1.48 +CAudioPolicy::CAudioPolicy(CMMFAudioPolicyServer* aAudioPolicyServer) :
    1.49 +	iAudioPolicyServer(aAudioPolicyServer)
    1.50 +	{
    1.51 +	}
    1.52 +
    1.53 +void CAudioPolicy::MakeRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest)
    1.54 +	{
    1.55 +	//Make sure there is sufficient space in the array to avoid expansion in AppendL() 
    1.56 +	__ASSERT_ALWAYS(iAudioPolicyRequestArray->Count() < iAudioPolicyServer->PolicySessionCount(), Panic(EMMFAudioPolicyRequestArrayOverflow));
    1.57 +	TPolicyResponse responseValue; 
    1.58 +	iSessionToAlert = NULL; // Reset
    1.59 +
    1.60 +	// Process Request by looking at priorities, preferences, special states...
    1.61 +	responseValue = ProcessRequest(aAudioPolicyRequest);
    1.62 +
    1.63 +		// Finally, check current profile settings (only if not denied thus far):
    1.64 +		//	CheckAgainstProfiles(aAudioPolicyRequest, responseValue);
    1.65 +		if (responseValue == EDenied)
    1.66 +			{
    1.67 +			SetSessionToAlert(aAudioPolicyRequest->PolicySessionId(),
    1.68 +							  NULL, TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow,
    1.69 +							  aAudioPolicyRequest->State());
    1.70 +			if(IsRegisteredNotification(aAudioPolicyRequest->PolicySessionId()))
    1.71 +				{
    1.72 +				TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
    1.73 +				__ASSERT_ALWAYS(err==KErrNone, Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
    1.74 +				}
    1.75 +			}
    1.76 +
    1.77 +	// If a client needs to be notified (either a previous session that was booted off or a new
    1.78 +	// one that was denied) then send event for that session to the client:
    1.79 +	// NB KErrInUse, KErrDied OR KErrAccessDenied may be used to indicate this.
    1.80 +	if (iSessionToAlert != NULL)
    1.81 +		{
    1.82 +			//check the session is registered for notification of resource available
    1.83 +			if(!IsRegisteredNotification(iSessionToAlert))
    1.84 +				{
    1.85 +				RemoveFromList(iSessionToAlert);  				
    1.86 +				}
    1.87 +			iAudioPolicyEvent.iErrorCode = KErrInUse;
    1.88 +			iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
    1.89 +			iAudioPolicyServer->SendEventToClient(iSessionToAlert, iSessionToBeLaunched, iAudioPolicyEvent);
    1.90 +		}
    1.91 +		//Resume of a Audio of the notified client ,since it is already in the list 
    1.92 +		//no need to append and send response back to DevSound for request accepted.
    1.93 +		if(responseValue == EResume)
    1.94 +			{
    1.95 +			iAudioPolicyServer->StopNotificationTimer();
    1.96 +			iAudioPolicyEvent.iErrorCode = KErrNone;
    1.97 +			iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent;
    1.98 +			iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
    1.99 +			iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent);	
   1.100 +			}
   1.101 +		// Add new policy to list, and send response back to DevSound for request accepted
   1.102 +	if (responseValue == EProceed)
   1.103 +		{
   1.104 +		//no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession
   1.105 +		TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
   1.106 +		__ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
   1.107 +		iAudioPolicyEvent.iErrorCode = KErrNone;
   1.108 +		iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent;
   1.109 +		iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
   1.110 +		iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent);
   1.111 +		}
   1.112 +	if (responseValue == EStopThenProceed)  // place on list, but dev Sound will launch request
   1.113 +		{
   1.114 +		//no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession
   1.115 +		TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
   1.116 +		__ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
   1.117 +		}
   1.118 +	}
   1.119 +
   1.120 +TPolicyResponse CAudioPolicy::ProcessRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest)
   1.121 +	{
   1.122 +	TPolicyResponse responseValue(EProceed); 
   1.123 +	iSessionToAlert = NULL; // Reset
   1.124 +
   1.125 +	// If there is no other item on list, return with proceed
   1.126 +	if (!iAudioPolicyRequestArray->Count()) 
   1.127 +		return EProceed;
   1.128 +	
   1.129 +	// Handle Preferences, if any, otherwise just compare priorities:
   1.130 +	//	HandlePreferences(aAudioPolicyRequest, preference, responseValue);
   1.131 +	if(IsNotified())
   1.132 +		{
   1.133 +		return EResume;
   1.134 +		}
   1.135 +	responseValue = ComparePriorities(aAudioPolicyRequest);
   1.136 +
   1.137 +	return responseValue;
   1.138 +	}
   1.139 +
   1.140 +void CAudioPolicy::ModifyEntry(TInt aPolicySessionId, CMMFAudioPolicyRequest* aAudioPolicyRequest)
   1.141 +	{
   1.142 +	TMMFAudioPolicyState requestState = aAudioPolicyRequest->State();
   1.143 +	// If state is stopped or paused, remove item from list
   1.144 +	if ((aAudioPolicyRequest->State() == EMMFStatePaused) || (aAudioPolicyRequest->State() == EMMFStateStopped) || (aAudioPolicyRequest->State() == EMMFStateCompleted))
   1.145 +		{
   1.146 +		if(iSessionToBeLaunched == aPolicySessionId)
   1.147 +			{
   1.148 +			iSessionToBeLaunched = 0;
   1.149 +			}
   1.150 +		if((aAudioPolicyRequest->State() == EMMFStateStopped) && (!iSessionToBeLaunched))
   1.151 +			{	
   1.152 +			TInt sessionToNotify = CheckSessionToNotify();
   1.153 +			if(sessionToNotify)
   1.154 +				{
   1.155 +				iAudioPolicyServer->StartNotificationTimer();
   1.156 +				iAudioPolicyEvent.iErrorCode = KErrNone;
   1.157 +				iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification;
   1.158 +				iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent);
   1.159 +				}	
   1.160 +			}
   1.161 +			if(aAudioPolicyRequest->NotificationEvent() != KMMFEventCategoryAudioResourceAvailable)
   1.162 +				{
   1.163 +				RemoveFromList(aPolicySessionId);	
   1.164 +				return;
   1.165 +				}
   1.166 +		}
   1.167 +	
   1.168 +	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.169 +		{
   1.170 +			// Find correct entry to replace state	
   1.171 +			if ( ((*iAudioPolicyRequestArray)[index].PolicySessionId()) == aPolicySessionId)
   1.172 +				{
   1.173 +					(*iAudioPolicyRequestArray)[index].SetState(requestState);
   1.174 +					break;
   1.175 +				}
   1.176 +		}  
   1.177 +	}
   1.178 +
   1.179 +void CAudioPolicy::RemoveFromList(TInt aPolicySessionId)
   1.180 +	{
   1.181 +	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.182 +		{
   1.183 +			// Find correct entry to remove	
   1.184 +			if ( (*iAudioPolicyRequestArray)[index].PolicySessionId() == aPolicySessionId)
   1.185 +				{
   1.186 +					iAudioPolicyRequestArray->Delete(index);
   1.187 +					break;
   1.188 +				}
   1.189 +		}  
   1.190 +	}
   1.191 +	
   1.192 +TPolicyResponse CAudioPolicy::ComparePriorities(CMMFAudioPolicyRequest* aAudioPolicyRequest/*, TMMFAudioPolicyEvent& aEvent*/)
   1.193 +	{
   1.194 +	TPolicyResponse responseValue(EProceed);
   1.195 +	TInt requestPriority = aAudioPolicyRequest->Priority();
   1.196 +
   1.197 +	TBool requestCaps = aAudioPolicyRequest->Capabilities();
   1.198 +
   1.199 +	// Iterate through list and compare priorities:
   1.200 +	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.201 +		{
   1.202 +			// If there's even one on the list w/ a higher priority deny request and leave:
   1.203 +
   1.204 +			if ((*iAudioPolicyRequestArray)[index].Capabilities() > requestCaps)
   1.205 +				{
   1.206 +				responseValue = EDenied;
   1.207 +				break;
   1.208 +				}
   1.209 +			else if((*iAudioPolicyRequestArray)[index].Capabilities() == requestCaps) 
   1.210 +				{
   1.211 +					if((*iAudioPolicyRequestArray)[index].Priority() >= requestPriority)
   1.212 +					{
   1.213 +						responseValue = EDenied;
   1.214 +						break;
   1.215 +					}
   1.216 +				}
   1.217 +
   1.218 +
   1.219 +			// Otherwise have the one on the list removed:
   1.220 +				SetSessionToAlert((*iAudioPolicyRequestArray)[index].PolicySessionId(), 
   1.221 +					aAudioPolicyRequest->PolicySessionId(), TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow, aAudioPolicyRequest->State());
   1.222 +				responseValue = EStopThenProceed;
   1.223 +		}    
   1.224 +	return responseValue;
   1.225 +	}
   1.226 +
   1.227 +void CAudioPolicy::HandlePreferences(CMMFAudioPolicyRequest* /*aAudioPolicyRequest*/, TInt /*aPref*/, TPolicyResponse& /*aResponse*/)
   1.228 +	{
   1.229 +	}
   1.230 +
   1.231 +void CAudioPolicy::LaunchRequest()
   1.232 +	{
   1.233 +	if (iAudioPolicyEventToLaunch.iEventType == TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle)
   1.234 +		iAudioPolicyServer->LaunchRequest(iSessionToBeLaunched, iAudioPolicyEventToLaunch);
   1.235 +	}
   1.236 +
   1.237 +// Sets up session information for sending an event on a denied (or killed) request
   1.238 +void CAudioPolicy::SetSessionToAlert(TInt aSessionToAlert, TInt aSessionToBeLaunched, TMMFAudioPolicyEvent::TAudioPolicyEventType aEventType, TMMFAudioPolicyState aState )
   1.239 +	{
   1.240 +	iSessionToAlert = aSessionToAlert;
   1.241 +	iSessionToBeLaunched = aSessionToBeLaunched;
   1.242 +	iAudioPolicyEvent.iEventType = aEventType;
   1.243 +
   1.244 +	if (iSessionToBeLaunched != 0)  // When currently playing item needs to be stopped
   1.245 +		{
   1.246 +		iAudioPolicyEventToLaunch.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle;
   1.247 +		iAudioPolicyEventToLaunch.iState = aState;
   1.248 +		}
   1.249 +	}
   1.250 +
   1.251 +CArrayFixFlat<CMMFAudioPolicyRequest>* CAudioPolicy::AudioPolicyRequestArray()
   1.252 +	{
   1.253 +	return iAudioPolicyRequestArray;
   1.254 +	}
   1.255 +	
   1.256 +/**
   1.257 +@internalTechnology
   1.258 +
   1.259 +This function raises a panic
   1.260 +
   1.261 +@param	aError
   1.262 +		one of the several panics codes that may be raised by this dll
   1.263 +
   1.264 +@panic	EMMFAudioPolicyRequestArrayOverflow is raised when policyrequest array is full
   1.265 +*/
   1.266 +GLDEF_C void Panic(TMMFAudioPolicyPanicCodes aPanicCode)
   1.267 +	{
   1.268 +	User::Panic(KMMFAudioPolicyPanicCategory, aPanicCode);
   1.269 +	}
   1.270 +
   1.271 +// checks based on the session ,Is the session is registered for Notification 
   1.272 +TBool CAudioPolicy::IsRegisteredNotification(TInt aSessionId)
   1.273 +	{
   1.274 +	TUid event;
   1.275 + 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.276 + 		{
   1.277 + 		if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId)
   1.278 + 			{
   1.279 + 			event = (*iAudioPolicyRequestArray)[index].NotificationEvent();
   1.280 + 			if (event  == KMMFEventCategoryAudioResourceAvailable)
   1.281 + 				{
   1.282 + 				// only when the client is registered for KMMFEventCategoryAudioResourceAvailable event
   1.283 + 				return ETrue; 
   1.284 + 				}
   1.285 + 			break;	
   1.286 + 			} 
   1.287 + 		} 
   1.288 + 	return EFalse;
   1.289 +	}
   1.290 +
   1.291 +// checks the state,whether any client is already send notification
   1.292 +TBool CAudioPolicy::IsNotified()
   1.293 +	{
   1.294 + 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.295 + 		{
   1.296 +		if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified)
   1.297 +			{
   1.298 +			// In a instance only one client should have the state as EMMFStateNotified
   1.299 +			return ETrue;
   1.300 +			}
   1.301 + 		}
   1.302 + 	return EFalse;
   1.303 +	}
   1.304 +
   1.305 +// get the next highest priority of the client to notify 	
   1.306 +TInt CAudioPolicy::CheckSessionToNotify()
   1.307 +	{
   1.308 +	TInt nextHighestPriority= -100;
   1.309 +	TInt sessionToNotify = 0;
   1.310 +	TInt notificationIdx = -1;
   1.311 +	if(IsNotified())
   1.312 +		{
   1.313 +		return sessionToNotify;
   1.314 +		}
   1.315 +	// get the max priority and set the Index 		
   1.316 +	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.317 + 		{
   1.318 + 		if((nextHighestPriority <= (*iAudioPolicyRequestArray)[index].Priority()) && ((*iAudioPolicyRequestArray)[index].NotificationEvent() != KNullUid) && (!(*iAudioPolicyRequestArray)[index].IsEventNotified()))
   1.319 + 			{
   1.320 + 			nextHighestPriority = (*iAudioPolicyRequestArray)[index].Priority();
   1.321 + 			sessionToNotify = (*iAudioPolicyRequestArray)[index].PolicySessionId();
   1.322 + 			notificationIdx = index;
   1.323 + 			}
   1.324 + 		}
   1.325 + 	// set the state as notified	
   1.326 + 	if(notificationIdx != -1)
   1.327 + 		{
   1.328 + 		(*iAudioPolicyRequestArray)[notificationIdx].SetEventFlag(ETrue);	
   1.329 + 		(*iAudioPolicyRequestArray)[notificationIdx].SetState(EMMFStateNotified);	
   1.330 + 		}
   1.331 +  	return sessionToNotify;	
   1.332 +	}
   1.333 +
   1.334 +// send the message to the server 
   1.335 +void CAudioPolicy::DoSendNotification()
   1.336 +	{
   1.337 +	ResetNotification();
   1.338 +	TInt sessionToNotify = CheckSessionToNotify();
   1.339 +	if(sessionToNotify)
   1.340 +		{
   1.341 +		iAudioPolicyEvent.iErrorCode = KErrNone;
   1.342 +		iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification;
   1.343 +		iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent);
   1.344 +		}
   1.345 +	}
   1.346 +
   1.347 +// Set in the AudiopolicyRequestArray the uid registered
   1.348 +TInt CAudioPolicy::SetNotification(TInt aSessionId, TUid aEventType)
   1.349 +	{
   1.350 +	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.351 + 		{
   1.352 + 		if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId)
   1.353 + 			{
   1.354 + 			(*iAudioPolicyRequestArray)[index].SetNotificationEvent(aEventType);
   1.355 + 			return ETrue;	
   1.356 + 			}
   1.357 + 		}
   1.358 + 	return EFalse;
   1.359 +	}
   1.360 +
   1.361 +// cancel the state of the message notification to closed 
   1.362 +void 	CAudioPolicy::ResetNotification()
   1.363 +	{
   1.364 + 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   1.365 + 		{
   1.366 +		if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified)
   1.367 +			{
   1.368 +			(*iAudioPolicyRequestArray)[index].SetState(EMMFStateClosed);
   1.369 +			}
   1.370 + 		}
   1.371 + 	}
   1.372 +