--- /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 <ctsy/pluginapi/cmmdatapackage.h>
+#include <ctsy/pluginapi/mtelephonyaudiocontrol.h>
+
+// ======== 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<CCallDataPackage*>(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<CMmVoiceCallTsy*>(
+ 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<CCallDataPackage*>(aDataPackage);
+
+ callData->GetCallIdAndMode( callId, callMode );
+
+ CMmVoiceCallTsy* mmCall = reinterpret_cast<CMmVoiceCallTsy*>(
+ 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<CMmVoiceCallTsy*>(
+ 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<CMmVoiceLineTsy*>(
+ 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<CMmVoiceCallTsy*>(
+ 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<CMmVoiceCallTsy*>(
+ 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