diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmvoicelinetsy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/common_tsy/commontsy/src/mmtsy/cmmvoicelinetsy.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,562 @@ +// Copyright (c) 2006-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: +// + + + +//INCLUDES +#include "cmmvoicelinetsy.h" +#include "cmmphonetsy.h" +#include "cmmvoicecalltsy.h" +#include "cmmcallextinterface.h" +#include "cmmlinelist.h" +#include "cmmcalllist.h" +#include "cmmtsyreqhandlestore.h" +#include +#include + +// ======== MEMBER FUNCTIONS ======== + +CMmVoiceLineTsy::CMmVoiceLineTsy() + { + } + +void CMmVoiceLineTsy::ConstructL() + { + TFLOGSTRING("TSY: CMmVoiceLineTsy::ConstructL"); + CMmLineTsy::ConstructL(); + } + +CMmVoiceLineTsy* CMmVoiceLineTsy::NewL( + CMmPhoneTsy* aMmPhone, + RMobilePhone::TMobileService aMode, + const TDesC& aName, + CMmMessageManagerBase* aMessageManager, + MTelephonyAudioControl* aTelephonyAudioControl ) + { + TFLOGSTRING2("TSY: CMmVoiceLineTsy::NewL, Voice line %S created", &aName); + CMmVoiceLineTsy* mmLineTsy = NULL; + + if ( aMmPhone != NULL && ( aMode == RMobilePhone::EVoiceService + || aMode == RMobilePhone::EAuxVoiceService ) ) + { + mmLineTsy = new ( ELeave ) CMmVoiceLineTsy(); + CleanupClosePushL( *mmLineTsy ); + mmLineTsy->iMmPhone = aMmPhone; + mmLineTsy->iLineName = aName; + mmLineTsy->iLineMode = aMode; + mmLineTsy->iMessageManager = aMessageManager; + mmLineTsy->iTelephonyAudioControl = aTelephonyAudioControl; + mmLineTsy->ConstructL(); + CleanupStack::Pop(); + } + return mmLineTsy; + } + +CMmVoiceLineTsy::~CMmVoiceLineTsy() + { + TFLOGSTRING2("TSY: CMmVoiceLineTsy::~CMmVoiceLineTsy. Line name: %S", \ + &iLineName); + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::OpenNewObjectL +// This method creates a new name for a call and opens a new call. This method +// is called when the client uses RCall::OpenNewCall method. Currently the +// maximum number of opened calls from tsy is 20. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +CTelObject* CMmVoiceLineTsy::OpenNewObjectL( + TDes& aNewName ) + { + CMmVoiceCallTsy* mmCall = NULL; + + //Logic here to prevent creation of unlimited amount of call objects + //by clients. The proposed maximum amount of call objects is 20: + // + // - 2 voice call object (1 for each line for incoming calls + // - 1 data call object (for incoming data call) + // - 1 emergency call object + // - 1+7 call objects for Confence call (max number of CC participants) + // - phonebook 1 + // - javaphone 1 + // - WTA 1 + // - voice mail box 1 + // - csd 1 + // - fax 1 + // - 3rd party 2 + // + + //Incoming calls can not be created if the maximum number is exceeded! + if ( KMaxNumberOfCallObjectsFromTsy + > iMmPhone->CallList()->GetNumberOfObjects() ) + { + CreateNewCallName( aNewName ); + mmCall = CMmVoiceCallTsy::NewL( iMmPhone, this, iLineMode, aNewName, + iMessageManager, iTelephonyAudioControl ); + + iNameOfLastCallAdded = aNewName; + + // Add the new call to the list of calls + TInt ret = iMmPhone->CallList()->AddObject( mmCall ); + if ( KErrNone != ret ) + { + //If call cannot be added to CallList -> leave with KErrNoMemory + //CallList has to have information about every call. + mmCall->Close(); + mmCall = NULL; + User::Leave( KErrNoMemory ); + } + else + { + CompleteNotifyCallAdded( aNewName ); + } + } + else + { + User::Leave( KErrAccessDenied ); + } + + return mmCall; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::InitInternalAttributesL +// Initialises miscellaneous internal attributes. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +void CMmVoiceLineTsy::InitInternalAttributesL() + { + CMmLineTsy::InitInternalAttributesL(); + + // The line supports voice connections. + iLineCaps.iFlags = RLine::KCapsVoice | RLine::KCapsEventIncomingCall; + + if( RMobilePhone::EAuxVoiceService == iLineMode ) + { + iLineCaps.iFlags |= RMobileLine::KCapsAuxVoice; + } + + //flag for swap handling + iSwapStatus = EStatusSwapNotRequested; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::CreateCallObjectForIncomingCall +// This function creates and stores a Call object that is used for a incoming +// call. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +TInt CMmVoiceLineTsy::CreateCallObjectForIncomingCall() + { + TInt trapError( KErrNone ); + TInt result( CMmPhoneTsy::EMultimodePhoneOutOfMemory ); + + if ( !iCallForIncomingCall ) + { + TName newName; + CreateNewCallName( newName ); + + TRAP( trapError, + iCallForIncomingCall = CMmVoiceCallTsy::NewL( + iMmPhone, this, iLineMode, newName, iMessageManager, + iTelephonyAudioControl ); + ); + + if ( trapError == KErrNone ) + { + iNameOfLastCallAdded = newName; + // Don't add the new call to the list of calls yet. Will be + // Added when incoming call has been received... + result = KErrNone; + } + } + return result; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::CreateGhostCallObject +// This method creates a Call object for the Ghost call. A ghost call is a +// call that has been initiated bypassing the ETel. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +CMmCallTsy* CMmVoiceLineTsy::CreateGhostCallObject( + TInt aCallId, + RMobilePhone::TMobileService, + RMobileCall::TMobileCallStatus aCallStatus ) + { + TInt trapError( KErrNone ); + + TName newName; + CreateNewCallName( newName ); + CMmVoiceCallTsy* mmCall = NULL; + + TRAP( trapError, ( mmCall = CMmVoiceCallTsy::NewL( iMmPhone, + this, iLineMode, newName, iMessageManager, + iTelephonyAudioControl ) ) ); + + if ( KErrNone == trapError && NULL != mmCall ) + { + //set call ID + mmCall->SetCallId( aCallId ); + //set call status + if( aCallStatus >= RMobileCall::EStatusDialling ) + { + //Status is allways set to dialing. If call is alredy + //e.g. connecting, missed status changes are simulated. + mmCall->SetCallStatus( + RCall::EStatusDialling, RMobileCall::EStatusDialling ); + } + //set call caps + mmCall->SetCallCaps( RCall::KCapsVoice | RCall::KCapsHangUp ); + //set call direction to MO call + mmCall->SetCallDirection( RMobileCall::EMobileOriginated ); + //set flag indicating that this is a ghost call + mmCall->SetGhostCall( ETrue ); + //save name of the last added call + iNameOfLastCallAdded = mmCall->CallName(); + } + return mmCall; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::CompleteNotifyIncomingCall +// This method notifies clients about incoming call. Basic information: one +// Call object is allocated in the boot-up for incoming call. When an incoming +// call occurs the call object will be given to the client that answers the +// call. Therefore TSY creates a new call object for the next incoming call. +// In case of out of memory situation, the next incoming call cannot be +// received! General error message about OutOfMemory situation is sent to the +// client. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +void CMmVoiceLineTsy::CompleteNotifyIncomingCall( + CMmDataPackage* aDataPackage ) + { + TInt callId( -1 ); + RMobilePhone::TMobileService callMode( RMobilePhone::EVoiceService ); + + CCallDataPackage* callDataPackage = + reinterpret_cast(aDataPackage); + + callDataPackage->GetCallIdAndMode( callId, callMode ); + + TFLOGSTRING3("TSY: CMmVoiceLineTsy::CompleteNotifyIncomingCall - Line \ + name: %S, Call id: %d", &iLineName, callId ); + + //reset req handle. Returns the deleted req handle + TTsyReqHandle reqHandle = iTsyReqHandleStore->ResetTsyReqHandle( + EMultimodeLineNotifyIncomingCall ); + + CMmVoiceCallTsy* mmCall = NULL; + + // Check if notification is requested + if ( EMultimodeLineReqHandleUnknown != reqHandle ) + { + mmCall = reinterpret_cast( + CallObjectForIncomingCall() ); + + if ( mmCall ) + { + // Add the new call to the list of calls + TInt ret = iMmPhone->CallList()->AddObject( mmCall ); + + if ( KErrNone == ret ) + { + //set flag indicating that this is a unowned incoming call + mmCall->SetUnownedCallObjectFlag( ETrue ); + //set call ID + mmCall->SetCallId( callId ); + // Set call direction to EMobileTerminated + mmCall->SetCallDirection( RMobileCall::EMobileTerminated ); + + // Add answer capability and remove dial capability to + // existing call capabilities + TUint32 callCaps = mmCall->CallCaps(); + callCaps |= RCall::KCapsAnswer; + callCaps &= ~RCall::KCapsDial; + mmCall->SetCallCaps( callCaps ); + + //set data to gsm extension + //( direction added because not uppdated in messagehandler) + mmCall->ActiveCallExtension()->SetMobileCallData( + aDataPackage, RMobileCall::EMobileTerminated ); + + iNameOfCallForAnswering = mmCall->CallName(); + iNumCalls++; + + *iRetIncomingCallName = mmCall->CallName(); + iCallForIncomingCall = NULL; + ReqCompleted( reqHandle, KErrNone ); + + // Create and store a new Call Object for incoming call. + CreateCallObjectForIncomingCall(); + } + else + { + //call object could not be added to the call list. Incoming + //call cannot be received. + ReqCompleted( reqHandle, KErrNoMemory ); + } + } + else + { + //call object could not be get. Incoming call cannot be received. + //General error message about OutOfMemory situation has been sent + //to the client. + ReqCompleted( reqHandle, KErrNoMemory ); + } + } + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::CompleteNotifyDiallingStatus +// This method notifies line that a call has entered Dialling state. It means +// that Call ID should be saved and in case of ghost call a new call object +// should be created. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +void CMmVoiceLineTsy::CompleteNotifyDiallingStatus( + CMmDataPackage* aDataPackage ) + { + TFLOGSTRING("TSY: CMmVoiceLineTsy::CompleteNotifyDiallingStatus"); + TInt callId( -1 ); + TBool ghostCall( EFalse ); + RMobilePhone::TMobileService callMode( RMobilePhone::EVoiceService ); + + CCallDataPackage* callData = + reinterpret_cast(aDataPackage); + + callData->GetCallIdAndMode( callId, callMode ); + + CMmVoiceCallTsy* mmCall = reinterpret_cast( + iMmPhone->CallList()->GetMmCallByMode( callMode ) ); + + if ( NULL == mmCall ) + { + TFLOGSTRING("TSY: CMmVoiceLineTsy::CompleteNotifyDiallingStatus - \ + GhostCall"); + ghostCall = ETrue; + } + else + { + TBool result( EFalse ); + TBool resultNoFdnCheck( EFalse ); + TBool resultISV( EFalse ); + + //now we have to check, if this is a ghost call + result = mmCall->IsServiceLocallyRequested( + CMmCallTsy::EMultimodeCallDial ); + + //now we have to check, if this is a ghost call + resultNoFdnCheck = mmCall->IsServiceLocallyRequested( + CMmCallTsy::EMultimodeCallDialNoFdnCheck ); + //now we have to check, if this is a ghost call (3rd party ) + resultISV = mmCall->IsServiceLocallyRequested( + CMmCallTsy::EMultimodeCallDialISV ); + + if ( ( !result ) && ( !resultISV ) && ( !resultNoFdnCheck ) ) + { + result = mmCall->IsServiceLocallyRequested( + CMmCallTsy::EMultimodeMobileCallDialEmergencyCall ); + } + + if ( result || resultNoFdnCheck || resultISV ) + { +TFLOGSTRING("TSY: CMmVoiceLineTsy::CompleteNotifyDiallingStatus - Not Emergency call"); + for ( TInt i = 0; i < iMmPhone->CallList()->GetNumberOfObjects(); + i++ ) + { + mmCall = reinterpret_cast( + iMmPhone->CallList()->GetMmCallByIndex(i) ); + if ( mmCall->ServiceRequested( + CMmCallTsy::EMultimodeCallDial ) + || mmCall->ServiceRequested( + CMmCallTsy::EMultimodeMobileCallDialEmergencyCall ) + || ( mmCall->ServiceRequested( + CMmCallTsy::EMultimodeCallDialISV ) ) + || ( mmCall->ServiceRequested( + CMmCallTsy::EMultimodeCallDialNoFdnCheck ) ) ) + { + mmCall->SetCallId( callId ); +TFLOGSTRING2("TSY: CMmVoiceLineTsy::CompleteNotifyDiallingStatus - mmCall SetCallId: %d", callId); + mmCall->CompleteNotifyMobileCallInfoChange( + aDataPackage ); + break; + } + } + } + else + { + TFLOGSTRING("TSY: CMmVoiceLineTsy::CompleteNotifyDiallingStatus - \ + Dial not found"); + ghostCall = ETrue; + } + } + //Ghost call handling starts here + if ( ghostCall ) + { + //complete call added notification directly from here + CompleteNotifyAddBypassingCall( aDataPackage ); + } + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::IsSwapReady +// Contains the logic for determining if a Swap request is ready +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +TBool CMmVoiceLineTsy::IsSwapReady( + RMobileCall::TMobileCallStatus aCallStatus ) + { + TBool ret( EFalse ); + CMmVoiceLineTsy* otherVoiceLine = NULL; + + CMmLineList* lineList = iMmPhone->LineList(); + TInt numberOfObjectsInLineList = lineList->GetNumberOfObjects(); + RMobilePhone::TMobileService lineMode( + RMobilePhone::EServiceUnspecified ); + + //Required by ALS. We have to check what is the status of calls at the + //other line. This for loop find the other voice line (primary or aux). + for ( TInt i = 0; i < numberOfObjectsInLineList; i++ ) + { + CMmVoiceLineTsy* line = reinterpret_cast( + lineList->GetMmLineByIndex( i ) ); + + if ( line != this && line != NULL ) + { + lineMode = line->LineMode(); + if ( ( lineMode == RMobilePhone::EVoiceService ) || + ( lineMode == RMobilePhone::EAuxVoiceService ) ) + { + otherVoiceLine = line; + break; + } + } + } + + //is TSY still waiting both hold and connected status indications + if ( EWaitingHoldAndResumeOk == iSwapStatus ) + { + //TSY is still waiting both hold and connected status indications + if ( RMobileCall::EStatusHold == aCallStatus ) + { + //hold status indication received + //-> still waiting connected status indication + iSwapStatus = EWaitingResumeOk; + } + else if ( RMobileCall::EStatusConnected == aCallStatus ) + { + //connected status indication received + //-> still waiting hold status indication + iSwapStatus = EWaitingHoldOk; + } + } + //swap handling is going on. + else if ( ( EWaitingResumeOk == iSwapStatus && + RMobileCall::EStatusConnected == aCallStatus ) || + ( EWaitingHoldOk == iSwapStatus && + RMobileCall::EStatusHold == aCallStatus ) ) + { + CMmCallList* callList = iMmPhone->CallList(); + TInt numberOfObjectsInCallList = callList->GetNumberOfObjects(); + CMmVoiceCallTsy* mmCall = NULL; + //find the call object from which the swap was requested. + for ( TInt i = 0; i < numberOfObjectsInCallList; i++ ) + { + mmCall = reinterpret_cast( + callList->GetMmCallByIndex(i) ); + if ( mmCall->ServiceRequested( + CMmCallTsy::EMultimodeMobileCallSwap ) ) + { + //complete swap request when the correct object has been found + mmCall->CompleteSwap( KErrNone ); + break; + } + } + //clear swap status. + iSwapStatus = EStatusSwapNotRequested; + //return value indicating that Swap was completed. + ret = ETrue; + } + //swap handling is going on. This the case where the calls to be swapped + //are opened different lines (primary and aux). + else if ( otherVoiceLine ) + { + if ( ( EWaitingResumeOk == otherVoiceLine->SwapStatus() && + RMobileCall::EStatusConnected == aCallStatus ) || + ( EWaitingHoldOk == otherVoiceLine->SwapStatus() && + RMobileCall::EStatusHold == aCallStatus ) ) + { + CMmCallList* callList = iMmPhone->CallList(); + TInt numberOfObjectsInCallList = callList->GetNumberOfObjects(); + CMmVoiceCallTsy* mmCall = NULL; + //find the call object from which the swap was requested. + for ( TInt i = 0; i < numberOfObjectsInCallList; i++ ) + { + mmCall = reinterpret_cast( + callList->GetMmCallByIndex(i) ); + if ( mmCall->ServiceRequested( + CMmCallTsy::EMultimodeMobileCallSwap ) ) + { + //complete swap request when the correct object has found + mmCall->CompleteSwap( KErrNone ); + break; + } + } + //clear swap status. + iSwapStatus = EStatusSwapNotRequested; + //clear swap status also from the aux line + otherVoiceLine->SetSwapStatus( EStatusSwapNotRequested ); + + //return value indicating that Swap was completed. + ret = ETrue; + } + } + return ret; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::SetSwapStatus +// Sets status of Swap. This can be used by call objects opened from this line +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +void CMmVoiceLineTsy::SetSwapStatus( + CMmVoiceLineTsy::TSwapStatus aSwapStatus ) + { + iSwapStatus = aSwapStatus; + } + +// --------------------------------------------------------------------------- +// CMmVoiceLineTsy::SwapStatus +// Return status of Swap for this Line. This can be used by call objects +// opened from this line. +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +CMmVoiceLineTsy::TSwapStatus CMmVoiceLineTsy::SwapStatus() const + { + return iSwapStatus; + } + +// End of File