// Copyright (c) 1999-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:
// Implements the CSmsEventLogerClass
//
//
/**
@file
*/
#include "smsulog.h"
#include "smsumain.h"
#include "smsstacklog.h"
#include "gsmubuf.h"
#include "Gsmumsg.h"
#include "Gsmuelem.h"
#include <logwrap.h>
#include <logwraplimits.h>
/**
* Allocates and creates a logger.
*
* @param aFs File server handle
* @param aPriority Active object priority
* @return New CSmsEventLogger object
* @capability None
*/
EXPORT_C CSmsEventLogger* CSmsEventLogger::NewL(RFs& aFs,TInt aPriority)
{
LOGSMSU1("CSmsEventLogger::NewL()");
CSmsEventLogger* smseventlogger = new(ELeave) CSmsEventLogger(aPriority);
CleanupStack::PushL(smseventlogger);
smseventlogger->ConstructL(aFs);
CleanupStack::Pop();
return smseventlogger;
} // CSmsEventLogger::NewL
/**
* Destructor.
* @capability None
*/
EXPORT_C CSmsEventLogger::~CSmsEventLogger()
{
Cancel();
delete iLogEvent;
delete iLogWrapper;
} // CSmsEventLogger::~CSmsEventLogger
/**
* Adds an event to the log database.
*
* @param aStatus Asynchronous status word to signal when the operation is complete
* @param aSmsMessage The SMS message that the event concerns
* @param aData SMS PDU information for the event
* @param aStatusId Optional string to include in the log message, specified by
* resource ID
* @capability WriteUserData
*/
EXPORT_C void CSmsEventLogger::AddEvent(TRequestStatus& aStatus,const CSmsMessage& aSmsMessage,const TLogSmsPduData& aData,TInt* aStatusId)
{
LOGSMSU1("CSmsEventLogger::AddEvent");
__ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState));
iState=ESmsEventLoggerAddingEvent;
Queue(aStatus);
iSmsPDUData=aData;
iSmsPDUData.iType=aSmsMessage.Type();
TRAPD(ret,DoAddEventL(aSmsMessage,aStatusId));
if (ret!=KErrNone)
{
CompleteMyself(ret);
}
else
{
iLogWrapper->Log().AddEvent(*iLogEvent,iStatus);
SetActive();
}
} // CSmsEventLogger::AddEvent
/**
* Gets the specified event from the log.
*
* The event itself can be obtained using a subsequent call to Event().
*
* @param aStatus Asynchronous status word to signal when the operation is complete
* @param aId Log event ID for the event
* @capability ReadUserData
*/
EXPORT_C void CSmsEventLogger::GetEvent(TRequestStatus& aStatus,TLogId aId)
{
LOGSMSU1("CSmsEventLogger::GetEvent");
__ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState));
iState=ESmsEventLoggerGettingEvent;
Queue(aStatus);
iLogEvent->SetId(aId);
iLogWrapper->Log().GetEvent(*iLogEvent,iStatus);
SetActive();
} // CSmsEventLogger::GetEvent
/** Changes the details of an existing event.
Use GetEvent() to specify the event.
@param aStatus Asynchronous status word to signal when the operation is complete
@param aSmsMessage The SMS message that the event concerns
@param aTime SMS delivery time
@param aData SMS PDU information for the event
@param aStatusId Optional string to include in the log message, specified by
resource ID
@capability WriteUserData
*/
EXPORT_C void CSmsEventLogger::ChangeEvent(TRequestStatus& aStatus,const CSmsMessage& aSmsMessage, const TTime* aTime, const TLogSmsPduData& aData, TInt* aStatusId)
{
LOGSMSU1("CSmsEventLogger::ChangeEvent");
__ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState));
__ASSERT_DEBUG(aSmsMessage.LogServerId()==iLogEvent->Id(),SmsuPanic(KSmsuPanicWrongLogServerId));
__ASSERT_DEBUG(iSmsPDUData.iType==aSmsMessage.Type(),SmsuPanic(ESmsuUnexpectedSmsPDUType));
iState=ESmsEventLoggerChangingEvent;
Queue(aStatus);
iSmsPDUData=aData;
iSmsPDUData.iType=aSmsMessage.Type();
TRAPD(ret,SetDataL(aSmsMessage,aStatusId, aTime));
if (ret!=KErrNone)
{
Complete(ret);
}
else
{
iLogWrapper->Log().ChangeEvent(*iLogEvent,iStatus);
SetActive();
}
}
/**
* Changes the details of an existing event.
*
* Use GetEvent() to specify the event.
*
* @param aStatus Asynchronous status word to signal when the operation is complete
* @param aSmsMessage The SMS message that the event concerns
* @param aData SMS PDU information for the event
* @param aStatusId Optional string to include in the log message, specified by
* resource ID
* @capability WriteUserData
*/
EXPORT_C void CSmsEventLogger::ChangeEvent(TRequestStatus& aStatus, const CSmsMessage& aSmsMessage, const TLogSmsPduData& aData, TInt* aStatusId)
{
ChangeEvent(aStatus, aSmsMessage, NULL, aData, aStatusId);
} // CSmsEventLogger::ChangeEvent
/**
* Deletes an event.
*
* Use GetEvent() to specify the event.
*
* @param aStatus Asynchronous status word to signal when the operation is complete
* @capability WriteUserData
*/
EXPORT_C void CSmsEventLogger::DeleteEvent(TRequestStatus& aStatus)
{
// Ignore in code coverage - not used within the SMS stack.
BULLSEYE_OFF
LOGSMSU1("CSmsEventLogger::DeleteEvent");
__ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState));
iState=ESmsEventLoggerDeletingEvent;
Queue(aStatus);
iLogWrapper->Log().DeleteEvent(iLogEvent->Id(),iStatus);
SetActive();
BULLSEYE_RESTORE
}
void CSmsEventLogger::DoCancel()
{
// Ignore in code coverage - in order to test would need to cancel
// event logger request; as these called when receiving/sending SMS
// message would need to cancel these activities during event the
// logger request - too difficult to test. Need to add unit test.
BULLSEYE_OFF
LOGSMSU3("CSmsEventLogger::DoCancel [iStatus=%d, iState=%d]", iStatus.Int(), iState);
switch( iState )
{
case ESmsEventLoggerGettingEvent:
case ESmsEventLoggerAddingEvent:
case ESmsEventLoggerChangingEvent:
case ESmsEventLoggerDeletingEvent:
{
iLogWrapper->Log().Cancel();
} break;
default:
{
SmsuPanic(KSmsuPanicUnexpectedState);
} break;
}
// Handle completion of this Active Object. Note that the object
// may well still be active at this point...
if( TimedOut() )
{
Complete(KErrTimedOut);
}
else
{
Complete(KErrCancel);
}
BULLSEYE_RESTORE
}
CSmsEventLogger::CSmsEventLogger(TInt aPriority):
CSmsuActiveBase(aPriority),
iState(ESmsEventLoggerIdle)
{
// NOP
}
void CSmsEventLogger::ConstructL(RFs& aFs)
{
LOGSMSU1("CSmsEventLogger::ConstructL()");
iLogWrapper=CLogWrapper::NewL(aFs);
iLogEvent=CLogEvent::NewL();
} // CSmsEventLogger::ConstructL
void CSmsEventLogger::DoRunL()
{
LOGSMSU2("CSmsEventLogger::DoRunL [iStatus=%d]", iStatus.Int() );
switch (iState)
{
case ESmsEventLoggerGettingEvent:
{
if (iStatus.Int() == KErrNone)
{
TPckg<TLogSmsPduData> packeddata(iSmsPDUData);
packeddata.Copy(iLogEvent->Data());
}
}
break;
case ESmsEventLoggerAddingEvent:
case ESmsEventLoggerChangingEvent:
case ESmsEventLoggerDeletingEvent:
{
// NOP
}
break;
default:
{
User::Leave(KErrGeneral);
//SmsuPanic(KSmsuPanicUnexpectedState);
}
break;
}
//
// DoRunL() will now return to CSmsuActiveBase which if the object
// is not active, will call Complete().
//
} // CSmsEventLogger::DoRunL
void CSmsEventLogger::DoAddEventL(const CSmsMessage& aSmsMessage,TInt* aStatusId)
{
LOGSMSU2("CSmsEventLogger::DoAddEventL [statusID*=%d]", aStatusId);
// Reset event
CLogEvent* logevent=CLogEvent::NewL();
delete iLogEvent;
iLogEvent=logevent;
TBuf<KLogMaxDirectionLength> direction;
switch (aSmsMessage.Type())
{
// Incoming SMS
case CSmsPDU::ESmsDeliver:
{
LOGSMSU1("DoAddEventL ESmsDeliver");
GetStringL(direction,R_LOG_DIR_IN);
break;
}
case CSmsPDU::ESmsStatusReport:
{
LOGSMSU1("DoAddEventL ESmsStatusReport");
GetStringL(direction,R_LOG_DIR_IN);
break;
}
// Outgoing SMS
case CSmsPDU::ESmsSubmit:
{
LOGSMSU1("DoAddEventL ESmsSubmit");
GetStringL(direction,R_LOG_DIR_OUT);
break;
}
case CSmsPDU::ESmsCommand:
{
LOGSMSU1("DoAddEventL ESmsCommand");
GetStringL(direction,R_LOG_DIR_OUT);
break;
}
default:
{
LOGSMSU1("DoAddEventL ESmsuUnexpectedSmsPDUType");
SmsuPanic(ESmsuUnexpectedSmsPDUType);
}
}
Event().SetDirection(direction);
Event().SetEventType(KLogShortMessageEventTypeUid);
TGsmSmsTelNumber address;
aSmsMessage.ParsedToFromAddress(address);
if (address.IsInstanceOf(TGsmSmsTelNumber::EVoiceMessageWaitingIndicator))
{
Event().SetNumber(_L("CPHS"));
}
else
{
Event().SetNumber(aSmsMessage.ToFromAddress());
}
SetDataL(aSmsMessage,aStatusId, NULL);
} // CSmsEventLogger::DoAddEventL
void CSmsEventLogger::SetDataL(const CSmsMessage& aSmsMessage,TInt* aStatusId, const TTime* aDischargeTime)
{
__ASSERT_DEBUG(iSmsPDUData.iType==aSmsMessage.Type(),SmsuPanic(ESmsuUnexpectedSmsPDUType));
TBuf<KLogMaxStatusLength> status;
#ifdef _DEBUG
if (aStatusId!=NULL)
LOGSMSU2("CSmsEventLogger::SetDataL StatusID = %d", *aStatusId);
#endif
if (aStatusId==NULL)
{
CSmsPDU::TSmsPDUType type=aSmsMessage.Type();
switch (type)
{
// Incoming SMS
case CSmsPDU::ESmsDeliver:
{
if (iSmsPDUData.iTotal==iSmsPDUData.iReceived)
{
LOGSMSU1("SetDataL ESmsDeliver R_LOG_DEL_DONE");
GetStringL(status,R_LOG_DEL_DONE);
}
else if (iSmsPDUData.iTotal>iSmsPDUData.iReceived)
{
LOGSMSU1("SetDataL ESmsDeliver R_LOG_DEL_PENDING");
GetStringL(status,R_LOG_DEL_PENDING);
}
break;
}
case CSmsPDU::ESmsStatusReport:
{
if (iSmsPDUData.iTotal==iSmsPDUData.iReceived)
{
LOGSMSU1("SetDataL ESmsStatusReport R_LOG_DEL_DONE");
GetStringL(status,R_LOG_DEL_DONE);
}
else if (iSmsPDUData.iTotal>iSmsPDUData.iReceived)
{
LOGSMSU1("SetDataL ESmsStatusReport R_LOG_DEL_PENDING");
GetStringL(status,R_LOG_DEL_PENDING);
}
break;
}
// Outgoing SMS
case CSmsPDU::ESmsSubmit:
case CSmsPDU::ESmsCommand:
{
TBool statusreportrequest=EFalse;
if (type==CSmsPDU::ESmsSubmit)
{
CSmsSubmit& submit=(CSmsSubmit&) aSmsMessage.SmsPDU();
statusreportrequest=submit.StatusReportRequest();
}
else
{
CSmsCommand& command=(CSmsCommand&) aSmsMessage.SmsPDU();
statusreportrequest=command.StatusReportRequest();
}
if (statusreportrequest)
{
if (iSmsPDUData.iSent==0)
{
// None sent yet
GetStringL(status,R_LOG_DEL_NOT_SENT);
LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_NOT_SENT SR");
}
else if (iSmsPDUData.iTotal==iSmsPDUData.iDelivered)
{
// All have been delivered
LOGSMSU2("SetDataL ESmsSubmit R_LOG_DEL_DONE SR iSmsPDUData.iDelivered=%d", iSmsPDUData.iDelivered);
GetStringL(status,R_LOG_DEL_DONE);
}
else if (iSmsPDUData.iSent<=iSmsPDUData.iTotal && iSmsPDUData.iFailed==0)
{
// One or more sent but not all, no failures
LOGSMSU3("SetDataL ESmsSubmit R_LOG_DEL_PENDING SR iSmsPDUData.iSent==%d, iSmsPDUData.iTotal==%d, iFailed==0", iSmsPDUData.iSent, iSmsPDUData.iTotal);
GetStringL(status,R_LOG_DEL_PENDING);
}
else
{
// One or more failures or corruption of iSmsPDUData values
LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_FAILED SR");
LOGSMSU3(" Total: %d, Sent: %d",iSmsPDUData.iTotal, iSmsPDUData.iSent );
LOGSMSU3(" Failed: %d, Delivered: %d",iSmsPDUData.iFailed, iSmsPDUData.iDelivered );
GetStringL(status,R_LOG_DEL_FAILED);
}
if (aDischargeTime != NULL)
{
iLogEvent->SetTime(*aDischargeTime);
}
}
else
{
if (iSmsPDUData.iSent<iSmsPDUData.iTotal)
{
// IF not all PDUs sent, state is "NOT SENT".
LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_NOT_SENT NOSR");
LOGSMSU3(" Total: %d, Sent: %d", iSmsPDUData.iTotal, iSmsPDUData.iSent );
GetStringL(status,R_LOG_DEL_NOT_SENT);
}
else if (iSmsPDUData.iTotal==iSmsPDUData.iSent)
{
// All sent
LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_SENT NOSR");
GetStringL(status,R_LOG_DEL_SENT);
}
else
{
// The iSmsPDUData values have become corrupt
LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_FAILED NOSR");
LOGSMSU3(" Total: %d, Sent: %d",iSmsPDUData.iTotal, iSmsPDUData.iSent );
LOGSMSU3(" Failed: %d, Delivered: %d",iSmsPDUData.iFailed, iSmsPDUData.iDelivered );
GetStringL(status,R_LOG_DEL_FAILED);
}
}
LOGSMSU2("SetDataL [status string=%S]",&status);
break;
}
default:
{
LOGSMSU1("SetDataL ESmsuUnexpectedSmsPDUType");
SmsuPanic(ESmsuUnexpectedSmsPDUType);
}
}
}
else
GetStringL(status,*aStatusId);
TBuf<KLogMaxSubjectLength> subject;
//
// EDNAVSA-4VA9FQ Incoming SMSes with special chars are entered in the log as "data messages"
// only 8 bit messages are displayed as data message in the log viewer
//
if (aSmsMessage.SmsPDU().DataCodingSchemePresent() && aSmsMessage.SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit)
{
GetStringL(subject, R_LOG_SUBJECT_DATA_MESSAGE);
}
else if (aSmsMessage.TextPresent())
{
const TInt length= Min(KLogMaxSubjectLength, aSmsMessage.Buffer().Length());
aSmsMessage.Buffer().Extract(subject, 0, length);
subject.Trim();
}
if (subject.Length() == 0)
{
GetStringL(subject, R_LOG_SUBJECT_NONE);
}
iLogEvent->SetSubject(subject);
iLogEvent->SetStatus(status);
TPckg<TLogSmsPduData> packeddata(iSmsPDUData);
iLogEvent->SetDataL(packeddata);
} // CSmsEventLogger::SetDataL
void CSmsEventLogger::DoComplete(TInt& aStatus)
{
LOGSMSU3("CSmsEventLogger::DoComplete(): aStatus=%d, iState=%d", aStatus, iState);
//
// Check the state is valid and finish up...
//
__ASSERT_DEBUG(iState == ESmsEventLoggerGettingEvent ||
iState == ESmsEventLoggerAddingEvent ||
iState == ESmsEventLoggerChangingEvent ||
iState == ESmsEventLoggerDeletingEvent, SmsuPanic(KSmsuPanicUnexpectedState));
aStatus = -aStatus;
iState = ESmsEventLoggerIdle;
} // CSmsEventLogger::Complete