// Copyright (c) 1997-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:
//
/**
@file
*/
#include <commsdattypesv1_1.h>
#include <cdbcols.h>
#include "smspmain.h"
#include "smsuset.h"
#include "smspcdb.h"
#include "SmsuTimer.h"
using namespace CommsDat;
/**
* 2 phase constructor.
*
* @param aSmsSettings a reference to the global SMS settings.
* @param aSmsMessaging a reference to the ETEL SMS messaging subsession.
* @param aPriority of the request.
* @leave Leaves if ContructL() leaves, or not enough memory is available.
* @return a new CSmspSetBearer object
*/
CSmspSetBearer* CSmspSetBearer::NewL(const TSmsSettings& aSmsSettings,RMobileSmsMessaging& aSmsMessaging, TInt aPriority)
{
LOGSMSPROT2("CSmspSetBearer::NewL aPriority = %d", aPriority);
CSmspSetBearer* smsSetBearer=new(ELeave) CSmspSetBearer(aSmsSettings,aSmsMessaging, aPriority);
CleanupStack::PushL(smsSetBearer);
smsSetBearer->ConstructL();
CleanupStack::Pop();
return smsSetBearer;
} // CSmspSetBearer::NewL
/**
* 2-phase constructor, perform construction that can leave
*/
void CSmspSetBearer::ConstructL()
{
LOGSMSPROT1("CSmspSetBearer::ConstructL()");
CSmspCommDbEvent::ConstructL();
User::LeaveIfError(iProperty.Attach(KUidSystemCategory, KUidCommDbSMSBearerChange.iUid));
} // CSmspSetBearer::ConstructL
/**
* Private constructor used in the first phase of construction.
*
* @param aSmsSettings a reference to the global SMS settings.
* @param aSmsMessaging a reference to the ETEL SMS messaging subsession.
* @param aPriority of the request.
*
*/
CSmspSetBearer::CSmspSetBearer(const TSmsSettings& aSmsSettings, RMobileSmsMessaging& aSmsMessaging, TInt aPriority)
:CSmspCommDbEvent(aSmsSettings, aSmsMessaging, aPriority)
,iState(ESmsSetBearerStateInit)
{
} // CSmspSetBearer::CSmspSetBearer
/**
* CSmspSetBearer destructor
*/
CSmspSetBearer::~CSmspSetBearer()
{
Cancel();
} // CSmspSetBearer::~CSmspSetBearer
/**
* Notifies if SMS bearer is set to the TSY. Start setting bearer
* process if bearer is not set.
*/
void CSmspSetBearer::NotifyBearerSet(TRequestStatus& aStatus)
{
LOGSMSPROT2("CSmspSetBearer::NotifyBearerSet, aStatus = %d", aStatus.Int());
if (!iBearerSet && IsActive())
{
Cancel();
}
Queue(aStatus);
if (iBearerSet)
{
LOGSMSPROT1("CSmspSetBearer::NotifyBearerSet RequestComplete called");
CSmsuActiveBase::Complete(KErrNone);
}
else
{
LOGSMSPROT1("CSmspSetBearer::NotifyBearerSet started");
Start();
}
} // CSmspSetBearer::NotifyBearerSet
/**
* Starts the sequence for configuring the current SMS bearer on the phone/TSY.
*/
void CSmspSetBearer::Start()
{
LOGSMSPROT1("CSmspSetBearer::Start");
// Cancel any outstanding request
TRAPD(err, GetSmsBearerL(iBearer));
iBearerSet = EFalse;
if (err == KErrNone)
{
LOGSMSPROT2("CSmspSetBearer::GetSmsBearerL() left with %d", err);
// Set the previous bearer to the one that has been read
// from CommDB so that iPreviousBearer has an initial value
// when the smsstack is first started.
iPreviousBearer = iBearer;
SetSmsBearer();
}
else
{
LOGSMSPROT2("CSmspSetBearer::Start failed to get SMS bearer, error = %d", err);
Complete(err);
}
} // CSmspSetBearer::Start
/**
* Handles a completed request.
*
* Makes a state transition based on the result of the request and current state.
*
* @leave Panic if RunL is called while object is in idle state.
*/
void CSmspSetBearer::DoRunL()
{
LOGSMSPROT3("CSmspSetBearer::DoRunL(): iState=%d iStatus=%d", iState, iStatus.Int());
switch (iState)
{
case ESmsSetBearerNotifyOnEvent:
{
if (iStatus.Int() == KErrNone)
{
TInt tempBearer;
#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
CMDBSession *dbSession = CMDBSession::NewL(KCDVersion1_2);
#else
CMDBSession *dbSession = CMDBSession::NewL(KCDVersion1_1);
#endif
CleanupStack::PushL(dbSession);
CMDBRecordSet<CCDGlobalSettingsRecord> globalSettingsRecord(KCDTIdGlobalSettingsRecord);
TRAPD(err, globalSettingsRecord.LoadL(*dbSession));
if (err != KErrNone)
{
LOGSMSPROT2("CSmspSetBearer::DoRunL, could not load global settings, leave error code = %d", err);
User::Leave(err);
}
iPreviousBearer = iBearer;
LOGSMSPROT2("CSmspSetBearer::DoRunL Storing previous bearer setting. Previous bearer now = %d", iBearer);
tempBearer = ((CCDGlobalSettingsRecord*)globalSettingsRecord.iRecords[0])->iSMSBearer;
iBearer = static_cast<RMobileSmsMessaging::TMobileSmsBearer>(tempBearer);
CleanupStack::PopAndDestroy(dbSession);
SetSmsBearer();
}
else
{
NotifyOnEvent();
}
}
break;
case ESmsSetBearerStateSettingBearer:
{
if (iStatus.Int() == KErrNone)
{
iBearerSet = ETrue;
}
else
{
// Set bearer to previous value, if status!=KErrNone
// (e.g. KErrNotSupported)
// Set global setting to previous value,
// then complete.
LOGSMSPROT3("CSmspSetBearer::DoRunL TSY failed to set MO SMS bearer. status = %d. Bearer = %d", iStatus.Int(), iBearer);
iBearer = iPreviousBearer;
LOGSMSPROT2("CSmspSetBearer::DoRunL Setting bearer back to previous setting. Bearer = %d", iBearer);
#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
CMDBSession *dbSession = CMDBSession::NewL(KCDVersion1_2);
#else
CMDBSession *dbSession = CMDBSession::NewL(KCDVersion1_1);
#endif
CleanupStack::PushL(dbSession);
CMDBRecordSet<CCDGlobalSettingsRecord> globalSettingsRecord(KCDTIdGlobalSettingsRecord);
TRAPD(err, globalSettingsRecord.LoadL(*dbSession));
if (err != KErrNone)
{
LOGSMSPROT2("CSmspSetBearer::DoRunL could not load global settings, error = %d", err);
User::Leave(err);
}
((CCDGlobalSettingsRecord*)globalSettingsRecord.iRecords[0])->iSMSBearer = iPreviousBearer;
TRAP(err, globalSettingsRecord.ModifyL(*dbSession));
if (err != KErrNone)
{
LOGSMSPROT2("CSmspSetBearer::DoRunL could not modify global settings, error = %d", err);
User::Leave(err);
}
CleanupStack::PopAndDestroy(dbSession);
}
}
break;
default:
{
SmspPanic(KSmspPanicUnexpectedState);
}
break;
}
//
// DoRunL() will now return to CSmsuActiveBase which if the object
// is not active, will call Complete().
//
} // CSmspSetBearer::DoRunL
/**
* Handles a request to cancel the state machine.
* Cancels any outstanding request and calls Complete().
*/
void CSmspSetBearer::DoCancel()
{
LOGSMSPROT1("CSmspSetBearer::DoCancel");
TimedSetActiveCancel();
// Explicitly set iBearerSet to false to ensure new bearer is set on each execution
iBearerSet = EFalse;
switch (iState)
{
case ESmsSetBearerStateInit:
{
// NOP
}
break;
case ESmsSetBearerStateSettingBearer:
{
iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingSetMoSmsBearer);
}
break;
case ESmsSetBearerNotifyOnEvent:
{
iProperty.Cancel();
}
break;
default:
{
SmspPanic(KSmspPanicUnexpectedState);
}
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);
}
} // CSmspSetBearer::DoCancel
/**
* Performs the state transition to CSmspSetBearer::ESmsSetBearerStateQueryingCommDb by
* querying CommDB for the current value.
*
* @param aBearer a reference to the TMobileSmsBearer.
*/
void CSmspSetBearer::GetSmsBearerL(RMobileSmsMessaging::TMobileSmsBearer& aBearer)
{
LOGSMSPROT1("CSmspSetBearer::GetSmsBearerL()");
#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
CMDBSession* sess = CMDBSession::NewL(KCDVersion1_2);
#else
CMDBSession* sess = CMDBSession::NewL(KCDVersion1_1);
#endif
CleanupStack::PushL(sess);
CMDBField<TUint32>* smsBearerField = NULL;
smsBearerField = new(ELeave) CMDBField<TUint32>(KCDTIdSMSBearer);
CleanupStack::PushL(smsBearerField);
smsBearerField->SetRecordId(1);
smsBearerField->LoadL(*sess);
aBearer = static_cast<RMobileSmsMessaging::TMobileSmsBearer>(static_cast<TUint32>(*smsBearerField));
LOGSMSPROT2("CSmspSetBearer::GetSmsBearerL(): aBearer=%d", aBearer);
CleanupStack::PopAndDestroy(smsBearerField);
CleanupStack::PopAndDestroy(sess);
} // CSmspSetBearer::GetSmsBearerL
/**
* Performs the state transition to CSmspSetBearer::ESmsSetBearerStateSettingBearer
* by trying to set the sms bearer on the phone/TSY.
*/
void CSmspSetBearer::SetSmsBearer()
{
LOGSMSPROT2("CSmspSetBearer::SetSmsBearer, iBearer = %d", iBearer);
iBearerSet = EFalse;
iState = ESmsSetBearerStateSettingBearer;
iSmsMessaging.SetMoSmsBearer(iStatus, iBearer);
TimedSetActive(iSmsSettings.Timeout());
} // CSmspSetBearer::SetSmsBearer
/**
* Wait for notification from property for when the CommDB global setting SMS_BEARER changes
*/
void CSmspSetBearer::NotifyOnEvent()
{
LOGSMSPROT1("CSmspSetBearer::NotifyOnEvent");
iState = ESmsSetBearerNotifyOnEvent;
CSmspCommDbEvent::NotifyOnEvent();
} // CSmspSetBearer::NotifyOnEvent