os/mm/devsound/sounddevbt/src/server/Policy/MmfBtAudioPolicy.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include "MmfBtAudioPolicy.h"
    17 #include "MmfBtAudioPolicySession.h"	
    18 #include "MmfBtAudioPolicyServer.h"
    19 #include "MdaBtHwInfo.h"	
    20 #include "MmfBtAudioPolicyRequest.h"
    21 
    22 CAudioPolicy::~CAudioPolicy()
    23 	{
    24 	delete iMdaHwInfo;
    25 	delete iAudioPolicyRequestArray; 		
    26 	}
    27 
    28 void CAudioPolicy::ConstructL()
    29 	{
    30 	// Create dynamic array for sessions list
    31 	iAudioPolicyRequestArray = new(ELeave)CArrayFixFlat<CMMFAudioPolicyRequest>(CAudioPolicy::EGranularity);
    32 	iMdaHwInfo = CMdaHwInfo::NewL();
    33 	}
    34 
    35 EXPORT_C CAudioPolicy* CAudioPolicy::NewL(CMMFAudioPolicyServer* aAudioPolicyServer)
    36 	{	
    37 
    38 	CAudioPolicy* self = new(ELeave)CAudioPolicy(aAudioPolicyServer);
    39 	CleanupStack::PushL(self);
    40 	self->ConstructL();
    41 	CleanupStack::Pop();
    42 	return(self);
    43 	}
    44 
    45 CAudioPolicy::CAudioPolicy(CMMFAudioPolicyServer* aAudioPolicyServer) :
    46 	iAudioPolicyServer(aAudioPolicyServer)
    47 	{
    48 	}
    49 
    50 void CAudioPolicy::MakeRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest)
    51 	{
    52 	//Make sure there is sufficient space in the array to avoid expansion in AppendL() 
    53 	__ASSERT_ALWAYS(iAudioPolicyRequestArray->Count() < iAudioPolicyServer->PolicySessionCount(), Panic(EMMFAudioPolicyRequestArrayOverflow));
    54 	TPolicyResponse responseValue; 
    55 	iSessionToAlert = NULL; // Reset
    56 
    57 	// Process Request by looking at priorities, preferences, special states...
    58 	responseValue = ProcessRequest(aAudioPolicyRequest);
    59 
    60 		// Finally, check current profile settings (only if not denied thus far):
    61 		//	CheckAgainstProfiles(aAudioPolicyRequest, responseValue);
    62 		if (responseValue == EDenied)
    63 			{
    64 			SetSessionToAlert(aAudioPolicyRequest->PolicySessionId(),
    65 							  NULL, TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow,
    66 							  aAudioPolicyRequest->State());
    67 			if(IsRegisteredNotification(aAudioPolicyRequest->PolicySessionId()))
    68 				{
    69 				TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
    70 				__ASSERT_ALWAYS(err==KErrNone, Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
    71 				}
    72 			}
    73 
    74 	// If a client needs to be notified (either a previous session that was booted off or a new
    75 	// one that was denied) then send event for that session to the client:
    76 	// NB KErrInUse, KErrDied OR KErrAccessDenied may be used to indicate this.
    77 	if (iSessionToAlert != NULL)
    78 		{
    79 			//check the session is registered for notification of resource available
    80 			if(!IsRegisteredNotification(iSessionToAlert))
    81 				{
    82 				RemoveFromList(iSessionToAlert);  				
    83 				}
    84 			iAudioPolicyEvent.iErrorCode = KErrInUse;
    85 			iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
    86 			iAudioPolicyServer->SendEventToClient(iSessionToAlert, iSessionToBeLaunched, iAudioPolicyEvent);
    87 		}
    88 		//Resume of a Audio of the notified client ,since it is already in the list 
    89 		//no need to append and send response back to DevSound for request accepted.
    90 		if(responseValue == EResume)
    91 			{
    92 			iAudioPolicyServer->StopNotificationTimer();
    93 			iAudioPolicyEvent.iErrorCode = KErrNone;
    94 			iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent;
    95 			iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
    96 			iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent);	
    97 			}
    98 		// Add new policy to list, and send response back to DevSound for request accepted
    99 	if (responseValue == EProceed)
   100 		{
   101 		//no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession
   102 		TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
   103 		__ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
   104 		iAudioPolicyEvent.iErrorCode = KErrNone;
   105 		iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyNoEvent;
   106 		iAudioPolicyEvent.iState = aAudioPolicyRequest->State();
   107 		iAudioPolicyServer->SendEventToClient(aAudioPolicyRequest->PolicySessionId(), NULL, iAudioPolicyEvent);
   108 		}
   109 	if (responseValue == EStopThenProceed)  // place on list, but dev Sound will launch request
   110 		{
   111 		//no possibility of expansion here as sufficient space for the array is reserved in advance during the creation of the policysession
   112 		TRAPD(err, iAudioPolicyRequestArray->AppendL(*aAudioPolicyRequest) );
   113 		__ASSERT_ALWAYS(err==KErrNone,Panic(EMMFAudioPolicyRequestArrayOverflow) ); // we reserved space, so shouldn't hit this
   114 		}
   115 	}
   116 
   117 TPolicyResponse CAudioPolicy::ProcessRequest(CMMFAudioPolicyRequest* aAudioPolicyRequest)
   118 	{
   119 	TPolicyResponse responseValue(EProceed); 
   120 	iSessionToAlert = NULL; // Reset
   121 
   122 	// If there is no other item on list, return with proceed
   123 	if (!iAudioPolicyRequestArray->Count()) 
   124 		return EProceed;
   125 	
   126 	// Handle Preferences, if any, otherwise just compare priorities:
   127 	//	HandlePreferences(aAudioPolicyRequest, preference, responseValue);
   128 	if(IsNotified())
   129 		{
   130 		return EResume;
   131 		}
   132 	responseValue = ComparePriorities(aAudioPolicyRequest);
   133 
   134 	return responseValue;
   135 	}
   136 
   137 void CAudioPolicy::ModifyEntry(TInt aPolicySessionId, CMMFAudioPolicyRequest* aAudioPolicyRequest)
   138 	{
   139 	TMMFAudioPolicyState requestState = aAudioPolicyRequest->State();
   140 	// If state is stopped or paused, remove item from list
   141 	if ((aAudioPolicyRequest->State() == EMMFStatePaused) || (aAudioPolicyRequest->State() == EMMFStateStopped) || (aAudioPolicyRequest->State() == EMMFStateCompleted))
   142 		{
   143 		if(iSessionToBeLaunched == aPolicySessionId)
   144 			{
   145 			iSessionToBeLaunched = 0;
   146 			}
   147 		if((aAudioPolicyRequest->State() == EMMFStateStopped) && (!iSessionToBeLaunched))
   148 			{	
   149 			TInt sessionToNotify = CheckSessionToNotify();
   150 			if(sessionToNotify)
   151 				{
   152 				iAudioPolicyServer->StartNotificationTimer();
   153 				iAudioPolicyEvent.iErrorCode = KErrNone;
   154 				iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification;
   155 				iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent);
   156 				}	
   157 			}
   158 			if(aAudioPolicyRequest->NotificationEvent() != KMMFEventCategoryAudioResourceAvailable)
   159 				{
   160 				RemoveFromList(aPolicySessionId);	
   161 				return;
   162 				}
   163 		}
   164 	
   165 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   166 		{
   167 			// Find correct entry to replace state	
   168 			if ( ((*iAudioPolicyRequestArray)[index].PolicySessionId()) == aPolicySessionId)
   169 				{
   170 					(*iAudioPolicyRequestArray)[index].SetState(requestState);
   171 					break;
   172 				}
   173 		}  
   174 	}
   175 
   176 void CAudioPolicy::RemoveFromList(TInt aPolicySessionId)
   177 	{
   178 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   179 		{
   180 			// Find correct entry to remove	
   181 			if ( (*iAudioPolicyRequestArray)[index].PolicySessionId() == aPolicySessionId)
   182 				{
   183 					iAudioPolicyRequestArray->Delete(index);
   184 					break;
   185 				}
   186 		}  
   187 	}
   188 	
   189 TPolicyResponse CAudioPolicy::ComparePriorities(CMMFAudioPolicyRequest* aAudioPolicyRequest/*, TMMFAudioPolicyEvent& aEvent*/)
   190 	{
   191 	TPolicyResponse responseValue(EProceed);
   192 	TInt requestPriority = aAudioPolicyRequest->Priority();
   193 
   194 	TBool requestCaps = aAudioPolicyRequest->Capabilities();
   195 
   196 	// Iterate through list and compare priorities:
   197 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   198 		{
   199 			// If there's even one on the list w/ a higher priority deny request and leave:
   200 
   201 			if ((*iAudioPolicyRequestArray)[index].Capabilities() > requestCaps)
   202 				{
   203 				responseValue = EDenied;
   204 				break;
   205 				}
   206 			else if((*iAudioPolicyRequestArray)[index].Capabilities() == requestCaps) 
   207 				{
   208 					if((*iAudioPolicyRequestArray)[index].Priority() >= requestPriority)
   209 					{
   210 						responseValue = EDenied;
   211 						break;
   212 					}
   213 				}
   214 
   215 
   216 			// Otherwise have the one on the list removed:
   217 				SetSessionToAlert((*iAudioPolicyRequestArray)[index].PolicySessionId(), 
   218 					aAudioPolicyRequest->PolicySessionId(), TMMFAudioPolicyEvent::EMMFAudioPolicyPriorityTooLow, aAudioPolicyRequest->State());
   219 				responseValue = EStopThenProceed;
   220 		}    
   221 	return responseValue;
   222 	}
   223 
   224 void CAudioPolicy::HandlePreferences(CMMFAudioPolicyRequest* /*aAudioPolicyRequest*/, TInt /*aPref*/, TPolicyResponse& /*aResponse*/)
   225 	{
   226 	}
   227 
   228 void CAudioPolicy::LaunchRequest()
   229 	{
   230 	if (iAudioPolicyEventToLaunch.iEventType == TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle)
   231 		iAudioPolicyServer->LaunchRequest(iSessionToBeLaunched, iAudioPolicyEventToLaunch);
   232 	}
   233 
   234 // Sets up session information for sending an event on a denied (or killed) request
   235 void CAudioPolicy::SetSessionToAlert(TInt aSessionToAlert, TInt aSessionToBeLaunched, TMMFAudioPolicyEvent::TAudioPolicyEventType aEventType, TMMFAudioPolicyState aState )
   236 	{
   237 	iSessionToAlert = aSessionToAlert;
   238 	iSessionToBeLaunched = aSessionToBeLaunched;
   239 	iAudioPolicyEvent.iEventType = aEventType;
   240 
   241 	if (iSessionToBeLaunched != 0)  // When currently playing item needs to be stopped
   242 		{
   243 		iAudioPolicyEventToLaunch.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicySwitchToIdle;
   244 		iAudioPolicyEventToLaunch.iState = aState;
   245 		}
   246 	}
   247 
   248 CArrayFixFlat<CMMFAudioPolicyRequest>* CAudioPolicy::AudioPolicyRequestArray()
   249 	{
   250 	return iAudioPolicyRequestArray;
   251 	}
   252 	
   253 /**
   254 @internalTechnology
   255 
   256 This function raises a panic
   257 
   258 @param	aError
   259 		one of the several panics codes that may be raised by this dll
   260 
   261 @panic	EMMFAudioPolicyRequestArrayOverflow is raised when policyrequest array is full
   262 */
   263 GLDEF_C void Panic(TMMFAudioPolicyPanicCodes aPanicCode)
   264 	{
   265 	User::Panic(KMMFAudioPolicyPanicCategory, aPanicCode);
   266 	}
   267 
   268 // checks based on the session ,Is the session is registered for Notification 
   269 TBool CAudioPolicy::IsRegisteredNotification(TInt aSessionId)
   270 	{
   271 	TUid event;
   272  	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   273  		{
   274  		if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId)
   275  			{
   276  			event = (*iAudioPolicyRequestArray)[index].NotificationEvent();
   277  			if (event  == KMMFEventCategoryAudioResourceAvailable)
   278  				{
   279  				// only when the client is registered for KMMFEventCategoryAudioResourceAvailable event
   280  				return ETrue; 
   281  				}
   282  			break;	
   283  			} 
   284  		} 
   285  	return EFalse;
   286 	}
   287 
   288 // checks the state,whether any client is already send notification
   289 TBool CAudioPolicy::IsNotified()
   290 	{
   291  	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   292  		{
   293 		if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified)
   294 			{
   295 			// In a instance only one client should have the state as EMMFStateNotified
   296 			return ETrue;
   297 			}
   298  		}
   299  	return EFalse;
   300 	}
   301 
   302 // get the next highest priority of the client to notify 	
   303 TInt CAudioPolicy::CheckSessionToNotify()
   304 	{
   305 	TInt nextHighestPriority= -100;
   306 	TInt sessionToNotify = 0;
   307 	TInt notificationIdx = -1;
   308 	if(IsNotified())
   309 		{
   310 		return sessionToNotify;
   311 		}
   312 	// get the max priority and set the Index 		
   313 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   314  		{
   315  		if((nextHighestPriority <= (*iAudioPolicyRequestArray)[index].Priority()) && ((*iAudioPolicyRequestArray)[index].NotificationEvent() != KNullUid) && (!(*iAudioPolicyRequestArray)[index].IsEventNotified()))
   316  			{
   317  			nextHighestPriority = (*iAudioPolicyRequestArray)[index].Priority();
   318  			sessionToNotify = (*iAudioPolicyRequestArray)[index].PolicySessionId();
   319  			notificationIdx = index;
   320  			}
   321  		}
   322  	// set the state as notified	
   323  	if(notificationIdx != -1)
   324  		{
   325  		(*iAudioPolicyRequestArray)[notificationIdx].SetEventFlag(ETrue);	
   326  		(*iAudioPolicyRequestArray)[notificationIdx].SetState(EMMFStateNotified);	
   327  		}
   328   	return sessionToNotify;	
   329 	}
   330 
   331 // send the message to the server 
   332 void CAudioPolicy::DoSendNotification()
   333 	{
   334 	ResetNotification();
   335 	TInt sessionToNotify = CheckSessionToNotify();
   336 	if(sessionToNotify)
   337 		{
   338 		iAudioPolicyEvent.iErrorCode = KErrNone;
   339 		iAudioPolicyEvent.iEventType = TMMFAudioPolicyEvent::EMMFAudioPolicyResourceNotification;
   340 		iAudioPolicyServer->SendEventToClient(sessionToNotify, NULL, iAudioPolicyEvent);
   341 		}
   342 	}
   343 
   344 // Set in the AudiopolicyRequestArray the uid registered
   345 TInt CAudioPolicy::SetNotification(TInt aSessionId, TUid aEventType)
   346 	{
   347 	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   348  		{
   349  		if((*iAudioPolicyRequestArray)[index].PolicySessionId() == aSessionId)
   350  			{
   351  			(*iAudioPolicyRequestArray)[index].SetNotificationEvent(aEventType);
   352  			return ETrue;	
   353  			}
   354  		}
   355  	return EFalse;
   356 	}
   357 
   358 // cancel the state of the message notification to closed 
   359 void 	CAudioPolicy::ResetNotification()
   360 	{
   361  	for (TInt index = 0; index < iAudioPolicyRequestArray->Count(); index++)
   362  		{
   363 		if((*iAudioPolicyRequestArray)[index].State() == EMMFStateNotified)
   364 			{
   365 			(*iAudioPolicyRequestArray)[index].SetState(EMMFStateClosed);
   366 			}
   367  		}
   368  	}
   369