diff -r 2eacb6118286 -r ba76fc04e6c2 phoneengine/loghandling/src/cpeloghandling.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phoneengine/loghandling/src/cpeloghandling.cpp Fri Jun 04 10:19:18 2010 +0100 @@ -0,0 +1,844 @@ +/* +* Copyright (c) 2003-2006 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: This file contains the implementation of CPELogHandling class +* member functions. +* +*/ + + + +// INCLUDE FILES +#include +#include +#include +#include +#include "cpeloghandling.h" +#include "cpelogevent.h" +#include "cpeloghandlingcommand.h" +#include "cpelogexternaldata.h" +#include +#include +#include +#include +#include +#include "cpeloginfo.h" +#include "cpelogextensionwrapper.h" + +// EXTERNAL DATA STRUCTURES +// None + +// EXTERNAL FUNCTION PROTOTYPES +/// None + +// CONSTANTS +// None + +// MACROS +// None + +// LOCAL CONSTANTS AND MACROS +// None + +// MODULE DATA STRUCTURES +// None + +// LOCAL FUNCTION PROTOTYPES +// None + +// ----------------------------------------------------------------------------- +// CPELogHandling::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +MPELogHandling* CPELogHandling::NewL + ( + MPEPhoneModelInternal& aModel, // Owner of the object + RFs& aFsSession // Handle to a file server session + ) + { + TEFLOGSTRING(KTAOBJECT, "LOG CPELogHandling::NewL start."); + CPELogHandling* self = + new ( ELeave ) CPELogHandling( aModel, aFsSession ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + TEFLOGSTRING(KTAOBJECT, "LOG CPELogHandling::NewL complete."); + return self; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::~CPELogHandling +// Destructor. +// ----------------------------------------------------------------------------- +// +/***************************************************** +* Series 60 Customer / LOGENG +* Series 60 LOGENG API +*****************************************************/ +EXPORT_C CPELogHandling::~CPELogHandling() + { + TEFLOGSTRING( KTAOBJECT, "LOG CPELogHandling::~CPELogHandling" ); + + delete iLogExternalData; + + iFreeLogEventArray.ResetAndDestroy(); + iActiveLogEventArray.ResetAndDestroy(); + // All created CPELogEvent objects must be either in Free or Active array + // That is, it would be error to destroy objects in queued array. + iQueuedLogEventArray.Reset(); + iActiveCallIds.Close(); + + delete iLogHandlingCommand; + delete iLogClient; + iPlugins.ResetAndDestroy(); + REComSession::FinalClose(); + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::CPELogHandling +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPELogHandling::CPELogHandling + ( + MPEPhoneModelInternal& aModel, + RFs& aFsSession + ) : iModel( aModel ), + iDataStore( *( aModel.DataStore( ) ) ), + iFsSession( aFsSession ), + iLogEventUnderProcessing( NULL ) + { + TEFLOGSTRING( KTAOBJECT, "LOG CPELogHandling::CPELogHandling" ); + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +/***************************************************** +* Series 60 Customer / LOGENG +* Series 60 LOGENG API +*****************************************************/ +void CPELogHandling::ConstructL() + { + TEFLOGSTRING( KTAOBJECT, "LOG CPELogHandling::ConstructL" ); + // Create new instace of the Log Client + iLogClient = CLogClient::NewL( iFsSession ); + + // Enumeration for incoming call, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringIn, R_LOG_DIR_IN ) ); + // Enumeration for outgoing call, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringOut, R_LOG_DIR_OUT ) ); + // Enumeration for missed call, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringMissed, R_LOG_DIR_MISSED ) ); + // Enumeration for delivery call, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringDelivery, R_LOG_DEL_NONE ) ); + // Enumeration for incoming auxiliary line, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringInAlt, R_LOG_DIR_IN_ALT ) ); + // Enumeration for outgoing auxiliary line, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringOutAlt, R_LOG_DIR_OUT_ALT ) ); + // Enumeration for unknown name, get from database + User::LeaveIfError( iLogClient->GetString( iLogStringUnknown, R_LOG_REMOTE_UNKNOWN ) ); + + iLogHandlingCommand = new (ELeave) CPELogHandlingCommand( *this, *iLogClient ); + + // Reserve some log events here. We delete these log event objects only on the destructor. + for( TInt entryIndex = 0; entryIndex < KPEMaximumNumberOfLogEvents; entryIndex++ ) + { + CPELogEvent* logEvent = CPELogEvent::NewL( *this, *iLogHandlingCommand ); + CleanupStack::PushL( logEvent ); + iFreeLogEventArray.AppendL( logEvent ); + CleanupStack::Pop( logEvent ); + } + // Compress free log event array as it would never contain more objects than create here + iFreeLogEventArray.Compress( ); + + iLogExternalData = CPELogExternalData::NewL( *this ); + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::SaveCallEntry +// Creates log info and initiates saving call log info by calling SaveCallInfoL. +// Do log handling cleanup in case of a leave. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CPELogHandling::SaveCallEntry + ( + const TInt aCallId + ) + { + TInt errorCode( KErrArgument ); + if ( CallIdCheck::IsVoice( aCallId ) || + CallIdCheck::IsVideo( aCallId ) + ) + { + CPELogInfo* logInfo( NULL ); + TRAP( errorCode, logInfo = CPELogInfo::NewL(); ); + + if ( logInfo ) + { + // continue gathering log data + + // set phonenumber and/or voip address + SetRemoteContact( aCallId, *logInfo ); + logInfo->SetEventData( aCallId, iDataStore ); + TRAP_IGNORE( + // Contact link can be big, not critical for basic functionality. + if ( &iDataStore.ContactId( aCallId ) ) + { + // Pack and add link + HBufC8* buf( iDataStore.ContactId( aCallId ).PackLC() ); + TEFLOGSTRING( KTAINT, "Contact id packed" ); + logInfo->SetContactLink( buf ); + CleanupStack::Pop( buf ); + } + // default logging strategy is used if error happens while using extension + UpdateLogInfoWithExtensionDataL( aCallId, *logInfo ) ); + + TRAP( errorCode, SaveCallInfoL( *logInfo ) ); + delete logInfo; + } + + if( errorCode != KErrNone ) + { + DoCleanup(); + } + } + return errorCode; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::SendMessage +// Method reroutes messages from other modules to the CPEPho-object +// Note that it does not use base class SendMessage. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::SendMessage + ( + const MEngineMonitor::TPEMessagesFromPhoneEngine aMessage, // The message id number of the message. + TInt aErrorCode + ) + { + if ( aMessage == MEngineMonitor::EPEMessageLogEventSaved ) + { + TEFLOGSTRING( KTAINT, "LOG CPELogHandling::SendMessage(), Log event saved" ); + + if (aErrorCode == KErrNone ) + { + // flag event entry as added; next event is to be just entry update. + iLogEventUnderProcessing->SetAdded( ); + } + + if ( iLogEventUnderProcessing->IsCompleted( ) ) + { + TEFLOGSTRING( KTAINT, "LOG CPELogHandling::SendMessage(), Log entry completed" ); + + DeleteArrayEntry( iLogEventUnderProcessing ); + } + + // Indicate that no processing of log event is in progress + iLogEventUnderProcessing = NULL; + + if ( iQueuedLogEventArray.Count( ) > 0 ) + { + TEFLOGSTRING( KTAINT, "LOG CPELogHandling::SendMessage(), Executing queued request" ); + + CPELogEvent* logEvent = iQueuedLogEventArray[0]; + iQueuedLogEventArray.Remove( 0 ); + iLogEventUnderProcessing = logEvent; + TRAPD( error, logEvent->SaveL( ) ); + if ( error != KErrNone ) + { + DoCleanup(); + } + } + } + else + { + TEFLOGSTRING2( KTAINT, "LOG CPELogHandling::SendMessage(), Message %d not supported", aMessage ); + } + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringIn +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringIn + ( + // None + ) + { + return iLogStringIn; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringOut +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringOut + ( + // None + ) + { + return iLogStringOut; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringMissed +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringMissed + ( + // None + ) + { + return iLogStringMissed; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringIn +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringDelivery + ( + // None + ) + { + return iLogStringDelivery; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringIn +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringInAlt + ( + // None + ) + { + return iLogStringInAlt; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringOutAlt +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringOutAlt + ( + // None + ) + { + return iLogStringOutAlt; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::LogStringUnknown +// Get log string. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TLogString& CPELogHandling::LogStringUnknown + ( + // None + ) + { + return iLogStringUnknown; + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::SetRemoteContact +// ----------------------------------------------------------------------------- +// +void CPELogHandling::SetRemoteContact( TInt aCallId, CPELogInfo& aLogInfo ) + { + aLogInfo.SetVoipAddress( KNullDesC() ); + + if ( iDataStore.CallDirection( aCallId ) + == RMobileCall::EMobileOriginated ) + { + TEFLOGSTRING2(KTAINT, + "LOG CPELogHandling::CreateLogInfo, WholeOutgoingPhoneNumber, aCallId: %d" + , aCallId ) + aLogInfo.SetPhoneNumber( iDataStore.WholeOutgoingPhoneNumber( aCallId ) ); + } + else + { + aLogInfo.SetPhoneNumber( iDataStore.RemotePhoneNumber( aCallId ) ); + } + + if ( EPECallTypeVoIP == iDataStore.CallType( aCallId ) ) + { + // voip address field must be used for voip calls + aLogInfo.SetVoipAddress( aLogInfo.PhoneNumber() ); + aLogInfo.SetPhoneNumber( KNullDesC() ); + } + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::SaveCallInfoL +// Update log external data. +// Call SaveEventL if event should be saved to log db. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPELogHandling::SaveCallInfoL + ( + const CPELogInfo& aLogInfo // Call information + ) + { + TEFLOGSTRING3( KTAINT, "LOG CPELogHandling::SaveCallInfoL(), [CallID: %d], [CallState: %d]", aLogInfo.CallId(), aLogInfo.CallState() ); + + if ( EPEStateConnected == aLogInfo.CallState() ) + { + // Insert the call ID to the active call array when the call state is connected. + TInt err = iActiveCallIds.InsertInOrder( aLogInfo.CallId() ); + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + + // Only for the first call set the first call start time + if ( iActiveCallIds.Count() == 1 ) + { + // For Last active call timer. See end part of UpdateLastCallTimer. + iLogExternalData->SetFirstCallStartTime( aLogInfo.CallStartTime() ); + } + + // We have already store the start time to log database on dialling/ringing state, + // but this is the real start time of call. + TBuf formattedTime; + formattedTime.Zero(); + aLogInfo.CallStartTime().FormatL( formattedTime, KPEESDWTimeFormat ); + TEFLOGSTRING2( KTAINT, "LOG CPELogHandling::SaveCallInfoL() Connected state iCallStartTime > formattedTime: %S", &formattedTime ); + } + else + { + // logsEntry handling only on Dialling/Ringing and Idle states. + if ( EPEStateIdle == aLogInfo.CallState() ) + { + iLogExternalData->UpdateCallTimers( aLogInfo ); + if ( aLogInfo.MissedCall() ) + { + iLogExternalData->IncreaseMissedCallValue( aLogInfo.CallId() ); + } + + TInt index = iActiveCallIds.FindInOrder( aLogInfo.CallId() ); + if ( index >= 0 ) + { + // When a call is disconnected, its ID is removed from the active call array. + iActiveCallIds.Remove( index ); + iLogExternalData->UpdateLastCallTimerByLine( aLogInfo ); + if ( iActiveCallIds.Count() == 0 ) + { + TInt duration = iLogExternalData->UpdateLastCallTimer( aLogInfo ); + iModel.DataStore()->SetCallDuration( duration ); + } + } + } + if ( aLogInfo.LoggingEnabled() ) + { + // We log all voice calls and the following data/fax calls to Log database + // MO external Data calls, + // MO external Fax calls, + // MT external Data calls + // MT external Fax calls, + // MT internal Data calls, + // We don't log the following data/fax calls to Log database + // MO internal Data calls + // MO internal Fax calls, + // MT internal Fax calls, + // these are logged by CSD agent. + // But we have to update timers for these calls. + + SaveEventL( aLogInfo ); + } + } + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::SaveEventL +// Update log database entry for an event. Manages event queueing. +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPELogHandling::SaveEventL + ( + const CPELogInfo& aLogInfo // Log information + ) + { + TInt index; + CPELogEvent* logEvent; + + + index = FindEventIndexById( aLogInfo.CallId() ); + if ( index == KErrNotFound ) + { + // a log event object can't be reused; + TEFLOGSTRING2( KTAINT, "LOG CPELogHandling::SaveEventL(), [CallID: %d]",aLogInfo.CallId() ); + TEFLOGSTRING2( KTAINT, "LOG CPELogHandling::SaveEventL(), [CallDirection: %d]", aLogInfo.CallDirection() ); + + if ( iFreeLogEventArray.Count() > 0 ) + { + // reuse an already created object from the array of the freed log event objects + logEvent = iFreeLogEventArray[ 0 ]; + iFreeLogEventArray.Remove( 0 ); + } + else + { + // create a new object; none available to be reused + logEvent = CPELogEvent::NewL( *this, *iLogHandlingCommand ); + } + + CleanupStack::PushL( logEvent ); + iActiveLogEventArray.AppendL( logEvent ); + CleanupStack::Pop( logEvent ); + } + else + { + // the log event object is already active but not completed. reuse it. + logEvent = iActiveLogEventArray[ index ]; + } + + __ASSERT_ALWAYS( logEvent, Panic(EPEPanicNullPointer) ); + + + // Save logInfo for possible queueing. + logEvent->UpdateLogInfoL( aLogInfo ); + + if ( iLogEventUnderProcessing ) + { + // queueing can not be done per event because log client + // would fail if new request is sent before the previous one + // has been processed even if they are for two different events. + // See Symbian doc for more details. + if ( iQueuedLogEventArray.Find( logEvent ) == KErrNotFound ) + { + TEFLOGSTRING( KTAINT, "LOG CPELogHandling::SaveEventL(), AO busy, request queued" ); + // queue the updated event only if event is not already queued + TInt error = iQueuedLogEventArray.Append( logEvent ); + if ( error != KErrNone ) + { + TEFLOGSTRING( KTAERROR, "LOG CPELogHandling::SaveEventL(), Append to QueuedArray failed!" ); + TEFLOGSTRING( KTAERROR, "LOG CPELogHandling::SaveEventL(), WARNING: Array Entry will be deleted to prevent memory leak." ); + + DeleteArrayEntry( logEvent ); + + User::LeaveIfError( error ); + } + } + else // the existing queued request will be executed with updated info + { + TEFLOGSTRING( KTAINT, "LOG CPELogHandling::SaveEvent(), AO busy, queued request already exists" ); + } + } + else + { + iLogEventUnderProcessing = logEvent; + logEvent->SaveL( ); + } + } + +// ----------------------------------------------------------------------------- +// CPELogsHandling::FindEventIndexById +// Find index number from array with given callid. +// ----------------------------------------------------------------------------- +// +TInt CPELogHandling::FindEventIndexById + ( + const TInt aCallId // Call identification number + ) + { + TEFLOGSTRING( KTAINT, + "Log Handling: CPELogHandling::FindEventIndexById() - 1" ); + for( TInt index = 0; index < iActiveLogEventArray.Count(); index++ ) + { + TEFLOGSTRING( KTAINT, + "Log Handling: CPELogHandling::FindEventIndexById() - 2" ); + if( (iActiveLogEventArray[ index ]->CallId() == aCallId) && + !(iActiveLogEventArray[ index ]->IsCompleted()) ) + { + TEFLOGSTRING( KTAINT, + "LOG CPELogHandling::FindEventIndexById() - 3" ); + return index; + } + } + TEFLOGSTRING( KTAINT, + "LOG CPELogHandling::FindEventIndexById() - 4" ); + return KErrNotFound; + } + +// ----------------------------------------------------------------------------- +// CPELogsHandling::DeleteArrayEntry +// Delete array's enty by given callid. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::DeleteArrayEntry + ( + CPELogEvent* aLogEvent + ) + { + TInt index = iActiveLogEventArray.Find( aLogEvent ); + TInt queuedIndex = iQueuedLogEventArray.Find( aLogEvent ); + TInt freeIndex = iFreeLogEventArray.Find( aLogEvent ); + + // Reset event before deletion + aLogEvent->ResetEvent( ); + aLogEvent->ResetLogInfo(); + + // Remove event from queued array as it is there by error and should not be processed after deletion + if ( queuedIndex != KErrNotFound ) + { + TEFLOGSTRING( KTAERROR, "LOG CPELogHandling::DeleteArrayEntry: WARNING Log event removed from queued event array. This should not happen." ) + iQueuedLogEventArray.Remove( queuedIndex ); + } + + if ( index != KErrNotFound ) + { + iActiveLogEventArray.Remove( index ); + } + else + { + TEFLOGSTRING( KTAERROR, "LOG CPELogHandling::DeleteArrayEntry: WARNING Log event NOT in active event array. This should not happen." ) + } + + if ( freeIndex == KErrNotFound ) + { + if ( iFreeLogEventArray.Count( ) < KPEMaximumNumberOfLogEvents ) + { + if (iFreeLogEventArray.Append( aLogEvent ) != KErrNone) + { + // prevent memory leak + delete aLogEvent; + } + } + else + { + // prevent memory leak + delete aLogEvent; + } + } + } + +// ----------------------------------------------------------------------------- +// CPELogsHandling::DoCleanup +// Do log handling cleanup in case of leave during handling of a log event. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::DoCleanup() + { + if ( iLogEventUnderProcessing ) + { + // delete log event entry only if save leaves and event is completed + // otherwise we expect more log events for the same entry that is no need to delete + if ( iLogEventUnderProcessing->SaveLeave( ) && + iLogEventUnderProcessing->IsCompleted( ) ) + { + TEFLOGSTRING( KTAERROR, + "LOG CPELogHandling::DoCleanup(), WARNING: Array Entry will be deleted to prevent memory leak." ); + + DeleteArrayEntry( iLogEventUnderProcessing ); + } + } + } + + +// ----------------------------------------------------------------------------- +// CPELogsHandling::ResetMissedCalls() +// Reset missed call. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::ResetMissedCalls( TInt aCallId ) + { + TEFLOGSTRING( KTAINT, + "LOG CPELogsHandling::ResetMissedCalls > SetMissedCall" ); + + TEFLOGSTRING2(KTAINT, + "LOG CPELogHandling::ResetMissedCalls, aCallId: %d" + , iDataStore.CallId() ); + iDataStore.SetMissedCall( EFalse, aCallId ); + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::UpdateLogInfoWithExtensionDataL +// Log information is not changed if some error happens with extension usage. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::UpdateLogInfoWithExtensionDataL( TInt aCallId, + CPELogInfo& aLogInfo ) + { + TUint serviceId( iDataStore.ServiceId( aCallId ) ); + CTelLoggingExtension& extension = LoggingExtensionL( serviceId ); + + // initialize extension with original remote contact number/address + const TPEPhoneNumber* origRemoteContact = NULL; + RMobileCall::EMobileOriginated == iDataStore.CallDirection( aCallId ) + ? origRemoteContact = &iDataStore.WholeOutgoingPhoneNumber( aCallId ) + : origRemoteContact = &iDataStore.RemotePhoneNumber( aCallId ); + __ASSERT_ALWAYS( NULL != origRemoteContact, User::Leave( KErrNotFound ) ); + extension.InitializeL( serviceId, *origRemoteContact ); + + RBuf phoneNumber; + CleanupClosePushL( phoneNumber ); + User::LeaveIfError( extension.GetPhoneNumber( phoneNumber ) ); + + RBuf voipAddress; + CleanupClosePushL( voipAddress ); + User::LeaveIfError( extension.GetVoipAddress( voipAddress ) ); + + RBuf myAddress; + CleanupClosePushL( myAddress ); + User::LeaveIfError( extension.GetMyAddress( myAddress ) ); + + RBuf remotePartyName; + CleanupClosePushL( remotePartyName ); + User::LeaveIfError( extension.GetRemotePartyName( remotePartyName ) ); + + // update log info with successfully queried extension data + SetExtensionData( aLogInfo, phoneNumber, voipAddress, + myAddress, remotePartyName ); + + CleanupStack::PopAndDestroy( 4, &phoneNumber ); + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::LoggingExtensionL +// ----------------------------------------------------------------------------- +// +CTelLoggingExtension& CPELogHandling::LoggingExtensionL( TUint aServiceId ) + { + TUid pluginUid = LoggingPluginIdentifierL( aServiceId ); + + CPELogExtensionWrapper* wrapper = NULL; + TInt pluginInd = + iPlugins.Find( pluginUid, CPELogExtensionWrapper::MatchByUid ); + if ( KErrNotFound == pluginInd ) + { + wrapper = CreateExtensionWrapperLC( pluginUid ); + iPlugins.AppendL( wrapper ); + CleanupStack::Pop( wrapper ); + } + else + { + wrapper = iPlugins[pluginInd]; + } + + __ASSERT_ALWAYS( NULL != wrapper, User::Leave( KErrNotFound ) ); + return *wrapper; + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::LoggingPluginIdentifierL +// Resolves plugin identifier for the given service. +// ----------------------------------------------------------------------------- +// +TUid CPELogHandling::LoggingPluginIdentifierL( TUint aServiceId ) const + { + TInt pluginUid( 0 ); + CSPSettings* settings = CSPSettings::NewLC(); + CSPProperty* property = CSPProperty::NewLC(); + + TInt result = settings->FindPropertyL( aServiceId, + EPropertyCallLoggingPluginId, *property ); + User::LeaveIfError( result ); + User::LeaveIfError( property->GetValue( pluginUid ) ); + CleanupStack::PopAndDestroy( property ); + CleanupStack::PopAndDestroy( settings ); + + return TUid::Uid( pluginUid ); + } + + +// ----------------------------------------------------------------------------- +// CPELogHandling::SetExtensionData +// Lengths of the descriptors gotten from plugin must be checked, because +// extension API does not set limits for data length. In case that phone number +// is available, voip address is not saved to logs. That enables user to select +// call type s/he wants when calling from logs. +// ----------------------------------------------------------------------------- +// +void CPELogHandling::SetExtensionData( CPELogInfo& aLogInfo, + const TDesC& aPhoneNumber, const TDesC& aVoipAddress, + const TDesC& aMyAddress, const TDesC& aRemotePartyName ) + { + if ( aPhoneNumber.Length() <= aLogInfo.PhoneNumber().MaxLength() ) + { + aLogInfo.SetPhoneNumber( aPhoneNumber ); + aLogInfo.SetVoipAddress( KNullDesC() ); + } + + if ( aVoipAddress.Length() <= aLogInfo.VoipAddress().MaxLength() ) + { + if ( KNullDesC() == aLogInfo.PhoneNumber() ) + { + aLogInfo.SetVoipAddress( aVoipAddress ); + } + } + + if ( aMyAddress.Length() <= aLogInfo.MyAddress().MaxLength() ) + { + aLogInfo.SetMyAddress( aMyAddress ); + } + + // Try to use user defined contact name from contacts, remote party name + // from extension or voip address from extension as a contact name to be + // saved in logs, in that order. + TBool noContactMatch = ( KNullDesC() == aLogInfo.Name() ); + if ( noContactMatch ) + { + if ( aRemotePartyName.Length() != 0 ) + { + aLogInfo.SetName( aRemotePartyName.Left( aLogInfo.Name().MaxSize() ) ); + } + else if ( KNullDesC() != aLogInfo.VoipAddress() ) + { + aLogInfo.SetName( aLogInfo.VoipAddress() ); + } + else + { + aLogInfo.SetName( aLogInfo.PhoneNumber() ); + } + } + } + +// ----------------------------------------------------------------------------- +// CPELogHandling::CreateExtensionWrapperLC +// ----------------------------------------------------------------------------- +// +CPELogExtensionWrapper* CPELogHandling::CreateExtensionWrapperLC( + const TUid& aPluginUid ) const + { + return CPELogExtensionWrapper::NewLC( aPluginUid ); + } + +// End of File