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 +