phoneclientserver/phoneserver/src/ussd/cphsrvussdmanager.cpp
changeset 33 8d5d7fcf9b59
child 36 7c428525956b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneclientserver/phoneserver/src/ussd/cphsrvussdmanager.cpp	Wed Jul 21 18:26:52 2010 +0300
@@ -0,0 +1,2189 @@
+/*
+* Copyright (c) 2002-2010 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:  USSD Manager.
+*
+*/
+
+// INCLUDE FILES
+#include "cphsrvussdmanager.h" 
+#include "phsrvutils.h" 
+#include "cphsrvussdsendhandler.h" 
+#include "cphsrvussdreceivehandler.h" 
+#include "cphsrvussdnotifynwrelease.h" 
+#include "cphsrvresourcemanager.h" 
+#include "cphsrvussdreplytimer.h" 
+#include "mphsrvussdmessagesentobserver.h" 
+#include "mphsrvphoneinterface.h" 
+#include "cphsrvussdsessioncancelwaiter.h" 
+
+#include <apacmdln.h>
+#include <apgtask.h>
+#include <bautils.h>
+#include <textresolver.h>
+#include <charconv.h>
+#include <gsmuelem.h>
+#include <exterror.h>
+#include <rmmcustomapi.h>
+
+#include <w32std.h>
+#include <apgcli.h>
+#include <cphcltussd.h> 
+#include <hbtextresolversymbian.h>
+#include <phoneserver.rsg> 
+#include "phsrvdebuginfo.h" 
+#include <e32property.h>
+#include <centralrepository.h>
+#include <coreapplicationuisdomainpskeys.h>
+
+
+// CONSTANTS
+const TInt KPhSrvDefaultValue = 0x00000000;
+// See SharedDataKeysVariant.h or NcnListInternalPSKeys.h
+// const TInt KPhSrvUssdNoTone = 0; 
+// const TInt KPhSrvUssdTimeOutObserverGranularity = 2;
+// const TInt KPhSrvUssdSentMessageObserverGranularity = 2;
+// See KUssdSecureId in phcltclientserver.h
+//const TInt KPhSrvUssdAppUID = 0x10005955; 
+
+const TInt KPhSrvUssdMessageQueryInterval = 500000; // 0.5 sec
+//const TInt KPhSrvUssdNoteExitPeriod = 500000; // 0.5 sec
+//
+const TUint KPhSrvUssdDefaultDCS = 0x0f;                        // 00001111
+
+const TUint KPhSrvUssdDcsAlphabetDefaultPrecededLanguage = 0x10;// 00010000
+const TUint KPhSrvUssdDcsAlphabetDefaultPrecededLanguageSkipChars3 = 3;
+const TUint KPhSrvUssdDcsAlphabetDefaultPrecededLanguageSkipChars2 = 2;
+const TUint KPhSrvUssdDcsAlphabetDefaultPrecededLanguageStartBit = 5;
+
+const TUint KPhSrvUssdDcsAlphabetUCS2PrecededLanguage = 0x11;   // 00010001
+const TUint KPhSrvUssdDcsAlphabetUCS2PrecededLanguageSkipChars = 2;
+
+const TUint KPhSrvUssdDcsGeneralInformationMask = 0xc0;         // 11000000
+const TUint KPhSrvUssdDcsGeneralInformation = 0x40;             // 01xxxxxx
+const TUint KPhSrvUssdDcsGeneralInformationCompressed = 0x20;   // xx1xxxxx
+const TUint KPhSrvUssdDcsGeneralInformationSimMask = 0x13;      // 00010011
+const TUint KPhSrvUssdDcsGeneralInformationSim = 0x12;          // xxx1xx10
+const TUint KPhSrvUssdDcsGeneralInformationAlphabetMask = 0x0c; // 00001100
+const TUint KPhSrvUssdDcsGeneralInformationAlphabet8Bit = 0x04; // xxxx01xx
+const TUint KPhSrvUssdDcsGeneralInformationAlphabetUCS2 = 0x08; // xxxx10xx
+
+const TUint KPhSrvUssdDcsMessageHandlingAlphabetMask = 0xf4;    // 11110100
+const TUint KPhSrvUssdDcsMessageHandlingAlphabet8Bit = 0xf4;    // 1111x1xx
+const TInt KPhrUssdNotifyArraySize = 1;
+
+// Refers to HbPopup::NoDismiss = 0
+const TInt KPhSrvUssdPopupDismissPolicy = 0; 
+// The time out only for testing, from CPhSrvUssdReplyTimer.cpp
+const TUint KPhSrvUssdTimeout = 300000000;
+
+// Use QT style localization
+_LIT(KUssdLocFilename, "ussd_");
+_LIT(KCommonLocFilename, "common_");
+_LIT(KLocPath, "z:\\resource\\qt\\translations");
+_LIT(KUssdReply, "txt_ussd_button_reply"); // Reply
+_LIT(KUssdExit, "txt_ussd_button_exit"); // Exit
+_LIT(KUssdNext, "txt_ussd_button_next"); //Next
+_LIT(KUssdYes, "txt_common_button_yes"); // Yes
+_LIT(KUssdNo, "txt_common_button_no"); // No
+_LIT(KUssdTitle, "txt_ussd_title_message"); // Message
+_LIT(KUssdDone, "txt_ussd_dpopinfo_done"); // Done
+_LIT(KUssdConfirm, "txt_ussd_info_there_are_still_unread_notifications");
+
+// MACROS
+
+#define _DPRINT_FLAGS() \
+    _DDPRINT( 4, "PhSrv.FLAGS.MsgTypeReply ", iMsgTypeReply ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.NwReleased   ", iNetworkReleased ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.SendingAck   ", iSendingAck ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.AcksToBeSent ", iAcksToBeSent ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.iSendRelease ", iSendRelease ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.iClearArray  ", iClearArray ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.iLaunchGMQ   ", iLaunchGMQ ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.NotifyCount  ", NotifyCount() ); \
+    _DDPRINT( 4, "PhSrv.FLAGS.iShowDone    ", iShowDone ); 
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// CLASS DECLARATION
+
+#ifndef TPHSRVUSSDALPHABETPACKER_H
+#define TPHSRVUSSDALPHABETPACKER_H
+
+// CONSTANTS
+const TUint8 KPhSrvUssdCarriageReturn = 0x0d;
+
+/**
+*  Packs and unpacks data encoded in an Ussd alphabet.
+*
+*  @since 1.0
+*/
+class TPhSrvUssdAlphabetPacker
+    {
+    public:  // Constructors and destructor
+
+        /**
+        * Constructor.
+        *
+        * @param aAlphabet The alphabet that is used.
+        * @param aIsBinary Is the data binary, that will be converted.
+        * @param aStartBit The start bit for conversion.
+        */
+        TPhSrvUssdAlphabetPacker(
+            TSmsDataCodingScheme::TSmsAlphabet aAlphabet,
+            TBool aIsBinary,
+            TInt aStartBit );
+
+
+    public: // New functions
+
+        /**
+        * Unpacks 7-bit buffer to 8-bit buffer.
+        *
+        * @param aIn Descriptor where the 7-bit buffer is.
+        * @param aOut 8-bit buffer to set the result.
+        * @param aNumUDUnits Buffer length.
+        * @return Length of the result buffer.
+        */
+        TInt UnpackL(
+            const TDesC8& aIn,
+            TDes8& aOut,
+            TInt aNumUDUnits );
+
+        /**
+        * Unpacks 7-bit buffer to 8-bit and converts to unicode.
+        *
+        * @param aCharacterSetConverter Does the converting.
+        * @param aFs File server session.
+        * @param aIn Packed 7-bit buffer.
+        * @param aOut Unicode buffer.
+        * @param aNumUDUnits Number of charahters.
+        * @return Number of used octets in 8-bit buffer.
+        */
+        TInt UnpackAndConvertL(
+            CCnvCharacterSetConverter& aCharacterSetConverter,
+            RFs& aFs,
+            const TDesC8& aIn,
+            TDes& aOut,
+            TInt aNumUDUnits );
+
+        /**
+        * Counts the needed octet amout.
+        *
+        * @param aNumUDUnits Number of source characters.
+        * @return Octets needed.
+        */
+        TInt PackedOctetsRequiredL( TInt aNumUDUnits ) const;
+
+
+    private:
+
+        // Private helper methods
+        TInt ElementSizeInBitsL() const;
+
+
+    private:    // Data
+
+        // The used coding alphabet.
+        TSmsDataCodingScheme::TSmsAlphabet iAlphabet;
+
+        // Is the packed data binary.
+        TBool iIsBinary;
+
+        // The start bit for packing.
+        TInt iStartBit;
+    };
+
+#endif // TPHSRVUSSDALPHABETPACKER_H
+
+
+// -----------------------------------------------------------------------------
+// TPhSrvUssdAlphabetPacker::TPhSrvUssdAlphabetPacker
+// Constructor.
+//
+// -----------------------------------------------------------------------------
+//
+TPhSrvUssdAlphabetPacker::TPhSrvUssdAlphabetPacker(
+    TSmsDataCodingScheme::TSmsAlphabet aAlphabet,
+    TBool aIsBinary,
+    TInt aStartBit)
+    : iAlphabet( aAlphabet ),iIsBinary( aIsBinary ),iStartBit( aStartBit )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// TPhSrvUssdAlphabetPacker::UnpackL
+// Unpacks user data units from aIn and appends to aOut.
+//
+// -----------------------------------------------------------------------------
+//
+TInt TPhSrvUssdAlphabetPacker::UnpackL(
+    const TDesC8& aIn,
+    TDes8& aOut,
+    TInt aNumUDUnits )
+    {
+    TInt length = aNumUDUnits;
+    // Ensure we've got enough  output buffer
+    if ( aOut.Length() + length > aOut.MaxLength() )
+        {
+        User::Leave(KErrCorrupt);
+        }
+
+    TInt elementSizeInBits = ElementSizeInBitsL();
+    if ( elementSizeInBits == 8 ) // 8-bit data?
+        {
+        aOut.Append( aIn );
+        }
+    else if ( elementSizeInBits == 7 ) // need unpacking from 7-bit data
+        {
+        // Get raw pointers and do unpacking
+        TUint8* outPtr = ( TUint8* )aOut.Ptr() + aOut.Length();
+        const TUint8* inPtr = aIn.Ptr();
+
+        for ( TInt i = 0; i < length; i++ )
+            {
+            TInt from = ( *inPtr >> iStartBit ) & 0x7F; // Take seven bits
+            if ( iStartBit )
+                {
+                inPtr++;
+                // Take more from next byte
+                from |= ( *inPtr << ( 8 - iStartBit ) ) & 0x7F;
+                }
+            outPtr[i] = ( TUint8 ) from;
+            iStartBit = ( iStartBit + 7 ) % 8; // roll: 0,1,2,...,6,7,0,1,2...
+            }
+
+        // The last character will be ignored if message ends
+        // on an octet bounday with CR.
+        if ( outPtr[ length-1 ] == KPhSrvUssdCarriageReturn && iStartBit == 0 )
+            {
+            length--;
+            }
+        aOut.SetLength( aOut.Length() + length );
+        }
+    else
+        {
+        __ASSERT_DEBUG(EFalse,
+            PhoneServerUtils::Panic( EPhoneServerPanicModeLogicFault ) );
+        }
+    return length;
+    }
+
+
+// -----------------------------------------------------------------------------
+// TPhSrvUssdAlphabetPacker::UnpackAndConvertL
+// Unpacks the converts the input data, aIn, and appends to aOut
+//
+// -----------------------------------------------------------------------------
+//
+TInt TPhSrvUssdAlphabetPacker::UnpackAndConvertL(
+    CCnvCharacterSetConverter& aCharacterSetConverter,
+    RFs& aFs,
+    const TDesC8& aIn,
+    TDes& aOut,
+    TInt aNumUDUnits )
+    {
+
+    // Unpack first
+    HBufC8* unpackedBuffer = HBufC8::NewLC( aNumUDUnits );
+    TPtr8 unpackedBufferPtr( unpackedBuffer->Des() );
+    UnpackL( aIn, unpackedBufferPtr,aNumUDUnits );
+
+    // Convert
+    CSmsAlphabetConverter* converter =
+        CSmsAlphabetConverter::NewLC(
+            aCharacterSetConverter, aFs, iAlphabet, iIsBinary );
+
+    TPtrC convertedPtr = converter->ConvertToNativeL( *unpackedBuffer );
+    if ( convertedPtr.Length() > ( aOut.MaxLength() - aOut.Length() ) )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    // Cleanup and return
+    aOut.Append( convertedPtr );
+    CleanupStack::PopAndDestroy( 2 );    // unpackedBuffer, converter
+    return aNumUDUnits;
+    }
+
+
+// -----------------------------------------------------------------------------
+// TPhSrvUssdAlphabetPacker::PackedOctetsRequiredL
+// Returns the number of octets needed to pack the specified number of
+//
+// -----------------------------------------------------------------------------
+//
+TInt TPhSrvUssdAlphabetPacker::PackedOctetsRequiredL( TInt aNumUDUnits ) const
+
+    {
+    TInt octetsRequired = 0;
+    TInt elementSizeInBits = ElementSizeInBitsL();
+    if ( elementSizeInBits == 8 )
+        {
+        octetsRequired=aNumUDUnits;
+        }
+    else
+        {
+        octetsRequired =
+            ( iStartBit+aNumUDUnits * elementSizeInBits + 7 ) / 8;  // Rounds up
+        }
+    return octetsRequired;
+    }
+
+// -----------------------------------------------------------------------------
+// TPhSrvUssdAlphabetPacker::ElementSizeInBitsL
+// Returns the size in bits of a UDL element for the alphabet.  Leaves if
+// invalid data coding scheme.
+// -----------------------------------------------------------------------------
+//
+TInt TPhSrvUssdAlphabetPacker::ElementSizeInBitsL() const
+    {
+    if (iIsBinary)
+        return 8;
+    switch ( iAlphabet )
+        {
+        case TSmsDataCodingScheme::ESmsAlphabet7Bit:
+            {
+            return 7;
+            }
+        case TSmsDataCodingScheme::ESmsAlphabet8Bit:
+        case TSmsDataCodingScheme::ESmsAlphabetUCS2:
+            {
+            return 8;
+            }
+        default:
+            {
+            User::Leave(KErrGsmSMSDataCodingSchemeNotSupported);
+            return 8;
+            }
+        }
+    }
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::CPhSrvUssdManager
+//
+// Constructor
+//
+// -----------------------------------------------------------------------------
+//
+CPhSrvUssdManager::CPhSrvUssdManager(
+    RFs& aFsSession,
+    CPhSrvResourceManager& aResourceManager
+    )
+    :CActive( EPriorityLow ),
+     iFsSession( aFsSession ),
+     iResourceManager( aResourceManager ),
+     iDeviceDialog( NULL ),
+     iDCS ( KPhCltDcsUnknown ),
+     iReturnResultPckg ( iReturnResult ),
+     iTextBuffer ( NULL )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::~CPhSrvUssdManager
+//
+// Destructor
+//
+// -----------------------------------------------------------------------------
+//
+CPhSrvUssdManager::~CPhSrvUssdManager()
+    {
+    _DPRINT( 4, "PhSrv.~CPhSrvUssdManager.start" );
+
+
+    delete iUssdSendHandler;
+    iUssdSendHandler = NULL;
+
+    delete iUssdReceiveHandler;
+    iUssdReceiveHandler = NULL;
+
+    delete iUssdNotifyNWRelease;
+    iUssdNotifyNWRelease = NULL;
+
+    Cancel();
+
+    iTimer.Close();
+    
+    delete iTextBuffer;
+    iTextBuffer = NULL;
+    
+    delete iDeviceDialog;
+    iDeviceDialog = NULL;
+
+    if ( iNotifyArray )
+        {
+        iNotifyArray->Reset();
+        }
+    delete iNotifyArray;
+    if ( iUssdReplyTimer )
+        {
+        iUssdReplyTimer->Stop();
+        }
+    delete iUssdReplyTimer;
+    iUssdReplyTimer = NULL;
+
+    iFsSession.Close();
+
+    iMobileUssdMessaging.Close();
+    
+    delete iMoAckCallback;
+
+    _DPRINT( 4, "PhSrv.~CPhSrvUssdManager.end" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ConstructL
+//
+// Symbian OS 2nd phase constructor
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::ConstructL( MPhSrvPhoneInterface& aPhoneInterface )
+    {
+    _DPRINT( 4, "PhSrv.ConstructL.Start" );
+    const TBool textResolver = HbTextResolverSymbian::Init( 
+        KUssdLocFilename, KLocPath );
+    _DDPRINT( 4, "PhSrv.ConstructL.ussd loc:", textResolver );
+    User::LeaveIfError( iTimer.CreateLocal() );
+
+    User::LeaveIfError( iMobileUssdMessaging.Open( aPhoneInterface.PhSrvMobilePhone() ) );
+
+    // Check support
+    RMobileUssdMessaging::TMobileUssdCapsV1 caps;
+    RMobileUssdMessaging::TMobileUssdCapsV1Pckg pckgCaps( caps );
+    User::LeaveIfError( iMobileUssdMessaging.GetCaps( pckgCaps ) );
+
+    if ( !( ( caps.iUssdTypes & RMobileUssdMessaging::KCapsMTUssd ) == 0 &&
+        ( caps.iUssdFormat & RMobileUssdMessaging::KCapsPackedString ) == 0 ) )
+        {
+        _DPRINT( 4, "PhSrv.CPhSrvUssdManager::ConstructL" );
+        iUssdReceiveHandler = new( ELeave ) CPhSrvUssdReceiveHandler(
+            *this,
+            iMobileUssdMessaging );
+        iUssdReceiveHandler->ConstructL();
+
+        iUssdNotifyNWRelease = new( ELeave )  CPhSrvUssdNotifyNWRelease(
+            *this,
+            iMobileUssdMessaging );
+
+        iUssdNotifyNWRelease->ConstructL();
+        }
+
+    iPhoneInterface = &aPhoneInterface;
+
+    SendHandlerL();
+    
+    iMoAckCallback = new (ELeave) CAsyncCallBack( TCallBack( MoAckCallback, this ), CActive::EPriorityIdle );
+
+    iVariantReadOnlyValues = KPhSrvDefaultValue;
+
+    User::LeaveIfError( GetTelephonyVariantData() );
+
+    _DDPRINT( 4, "PhSrv.ConstructL.iSatCanceled ", iSatCanceled );
+    _DDPRINT( 4, "PhSrv.ConstructL.iShowDone ", iShowDone );
+    iNotifyArray = new( ELeave ) CDesCArrayFlat( KPhrUssdNotifyArraySize );
+    _DPRINT( 4, "PhSrv.ConstructL.End" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::SendHandlerL
+//
+// The send handler.
+//
+// -----------------------------------------------------------------------------
+//
+CPhSrvUssdSendHandler& CPhSrvUssdManager::SendHandlerL()
+    {
+    // If SendHandler is not created, first check that MO Ussd
+    // is supported by the TSY.
+    _DPRINT( 4, "PhSrv.SendHandlerL.Start" );
+    if ( iUssdSendHandler == NULL )
+        {
+        _DPRINT( 4, "PhSrv.SendHandlerL.iUssdSendHandler.NULL" );
+        RMobileUssdMessaging::TMobileUssdCapsV1 caps;
+        RMobileUssdMessaging::TMobileUssdCapsV1Pckg pckgCaps( caps );
+        User::LeaveIfError( iMobileUssdMessaging.GetCaps( pckgCaps ) );
+        _DPRINT( 4, "PhSrv.SendHandlerL.iMobileUssdMessaging.GetCaps" );
+
+        if ( ( caps.iUssdTypes & RMobileUssdMessaging::KCapsMOUssd ) == 0 ||
+            ( caps.iUssdFormat & RMobileUssdMessaging::KCapsPackedString )
+            == 0 )
+            {
+            _DPRINT( 4, "PhSrv.SendHandlerL.KErrNotSupported" );
+            User::Leave( KErrNotSupported );
+            }
+
+        iUssdSendHandler =
+            new( ELeave ) CPhSrvUssdSendHandler(
+                *this,
+                iMobileUssdMessaging,
+                *iPhoneInterface );
+        }
+    _DPRINT( 4, "PhSrv.SendHandlerL.End" );
+    return *iUssdSendHandler;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::SendUssdL
+//
+// Send the USSD message.
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::SendUssdL(
+    const TDesC8& aMsgData,
+    RMobileUssdMessaging::TMobileUssdAttributesV1& aMsgAttribute,
+    MPhSrvUssdMessageSentObserver& aObserver )
+    {
+    _DPRINT( 4, "PhSrv.SendUssdL.Start ######" );
+    _DPRINT_FLAGS();
+    
+    if ( iObserver && iNetworkReleased ) 
+        {
+        // Network has been released but the previous send request is still alive.
+        // Cancel the pervious send operation, complete the old request with error
+        // and clean up the pointer.
+        _DPRINT( 4, "PhSrv.SendUssdL.Error.Complete.Existing" );
+        if ( iUssdSendHandler ) 
+            {
+            iUssdSendHandler->Cancel();
+            }
+        iObserver->UssdMessageSentObserverHandleResult( KErrSessionClosed );
+        iObserver = NULL;
+        }
+    
+    if ( iObserver || iSendingAck )
+        {
+        _DPRINT( 4, "PhSrv.SendUssdL.KErrInUse" );
+        // Other client is using the service.
+        User::Leave( KErrInUse );
+        }
+
+    // Check that message type is set
+    if( ( aMsgAttribute.iFlags & RMobileUssdMessaging::KUssdMessageType )
+        == 0 )
+        _DPRINT( 4, "PhSrv.SendUssdL.KUssdMessageType.0" );
+        {
+        // Mesasge type not set -> Set it.
+        aMsgAttribute.iFlags |= RMobileUssdMessaging::KUssdMessageType;
+        if ( NetworkWaitingForAnAnswer() )
+            {
+            // Network is waiting for an answer
+            _DPRINT( 4, "PhSrv.SendUssdL.EUssdMOReply" );   // debug print
+            aMsgAttribute.iType = RMobileUssdMessaging::EUssdMOReply;
+            }
+        else
+            {
+            _DPRINT( 4, "PhSrv.SendUssdL.EUssdMORequest" );  // debug print
+            aMsgAttribute.iType = RMobileUssdMessaging::EUssdMORequest;
+            }
+        }
+        
+    RMobileUssdMessaging::TMobileUssdAttributesV1Pckg attribs( aMsgAttribute );
+    iShowDone = ETrue;
+    _DPRINT( 4, "PhSrv.SendUssdL.iShowDone.ETrue" );
+    _DPRINT( 4, "PhSrv.SendUssdL.Send" );
+    SendHandlerL().SendUssdL( aMsgData , attribs );
+    iObserver = &aObserver;
+    // Not closing nor closed anymore
+    iNetworkReleased = EFalse;
+    iSendRelease = EFalse;
+    iClearArray = EFalse;
+    
+    // Reply timer can be killed here... Receive event might come right after this
+    // which will setup the timer again if needed.
+    if ( NetworkWaitingForAnAnswer() )
+        {
+        _DPRINT( 4, "PhSrv.SendUssdCancel.TimerStop" );   // debug print
+        iUssdReplyTimer->Stop();
+        }
+    _DPRINT( 4, "PhSrv.SendUssdL.End" );
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::NetworkWaitingForAnAnswer
+// -----------------------------------------------------------------------------
+//
+TBool CPhSrvUssdManager::NetworkWaitingForAnAnswer() 
+    {
+    return iUssdReplyTimer && iUssdReplyTimer->IsTimerActive();
+    }
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::SendUssdCancel
+//
+// Cancel the USSD sending.
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::SendUssdCancel()
+    {
+    _DPRINT( 4, "PhSrv.SendUssdCancel.Start #######" );
+
+    // Ack sending should not be canceled unless it's about terminating
+    // the whole session
+    _DPRINT_FLAGS();
+    if ( !iSendingAck || iSendRelease ) 
+        {
+        _DPRINT( 4, "PhSrv.SendUssdCancel.DoingCancel" );
+        iUssdSendHandler->SendUssdCancel();
+        }
+
+    if ( iHavePendingSatMessagePointer )
+        {
+        _DPRINT( 4, "PhSrv.SendUssdCancel.SatCancel" );
+        iSatCanceled = ETrue;
+        }
+    iObserver = NULL;
+    
+    SetActiveIfPendingNotificationsExist();
+    _DPRINT( 4, "PhSrv.SendUssdCancel.End" );
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::SetActiveIfPendingNotificationsExist
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::SetActiveIfPendingNotificationsExist()
+    {
+    if ( !IsActive() && NotifyCount() > 0 )
+        {
+        _DPRINT( 4, "PhSrv.AcrtivateIf.NotActiveSelf" );
+        iLaunchGMQ = ETrue;
+        iNotifyMessage = ETrue;
+        _DPRINT( 4, "PhSrv.SendUssdCancel.iNotifyMessage.ETrue" );
+        iTimer.After( iStatus , KPhSrvUssdMessageQueryInterval );
+        SetActive();
+        _DPRINT_FLAGS();
+        _DDPRINT( 4, "PhSrv.AcrtivateIf.SetActive ", iStatus.Int() );
+        }
+    }
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdNetworkObserverHandleSendEventL
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::UssdNetworkObserverHandleSendEventL( TInt aError )
+    {
+    // debug print
+    _DDPRINT(
+        4,
+        "PhSrv.UssdNetworkObserverHandleSendEventL.Start: ##### ",
+        aError );
+
+    // complete SAT if needed
+    if ( aError < KErrNone )
+        {
+ 
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleSendEventL.CompleteSat" );
+        CompleteSatL( NULL, aError );
+        }
+
+    if ( iObserver )
+        {
+ 
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleSendEventL.Observer" );
+
+        iObserver->UssdMessageSentObserverHandleResult( aError );
+        iObserver = NULL;
+        }
+    
+    iSendingAck = EFalse;
+    
+    AsyncProcessMoAcks();
+    
+    // debug print
+    _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleSendEventL.End" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdAppTaskExists
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+TBool CPhSrvUssdManager::UssdAppTaskExistsL()
+{   
+    TBool ret = EFalse;
+    RWsSession wsSession;
+    User::LeaveIfError(wsSession.Connect());
+    _DPRINT( 4, "PhSrv.UssdAppTaskExists.wsSession.Connect" );
+    CleanupClosePushL(wsSession);
+    TApaTaskList tasklist(wsSession);
+    TApaTask task = tasklist.FindApp( KUssdSecureId );
+    ret = task.Exists();
+
+    CleanupStack::PopAndDestroy();
+    return ret;
+}
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdNetworkObserverHandleReceivedEventL
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::UssdNetworkObserverHandleReceivedEventL(
+    const TDes8& aMsgData,
+    const RMobileUssdMessaging::TMobileUssdAttributesV1& aMsgAttributes,
+    TInt aError )
+    {
+    _DDPRINT(
+        4,
+        "PhSrv.UssdNetworkObserverHandleReceivedEventL.Start: ### ",
+        aError );
+    _DPRINT_FLAGS();
+    if ( aError != KErrNone )
+        {
+        TurnLightsOn(); //Ensure lights on
+ 
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleReceivedEventL.ShErNote" );
+        ShowErrorNoteL( aError );
+        }
+    else if ( iSendRelease )
+        {
+        // Ignore if sendrelease is to be done. If the message was
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleReceivedEventL.SendRelease.Ignore" );
+        }
+    else
+        {
+        UssdHandleReceivedEventL( aMsgData, aMsgAttributes );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdHandleReceivedEventL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::UssdHandleReceivedEventL(
+    const TDes8& aMsgData,
+    const RMobileUssdMessaging::TMobileUssdAttributesV1& aMsgAttributes )
+    {
+    // This always is either ongoing transaction or starting a new based
+    // on incoming message, mark transaction to be open.
+    iNetworkReleased = EFalse;
+        
+    // 2. Complete Send with some positive value.
+    if ( iObserver )
+        {
+ 
+        _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.Observer" );
+        UssdNetworkObserverHandleSendEventL( 1 ); // some positive value
+        }
+    
+    if ( aMsgAttributes.iFlags&RMobileUssdMessaging::KUssdMessageType &&
+         aMsgAttributes.iType == RMobileUssdMessaging::EUssdMTRequest )
+        {
+        // 3. Stop old reply timer and start new one if needed.
+        RestartReplyTimerL();
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleReceivedEventL.Timer.Stop" );
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleReceivedEventL.Timer.New" );
+        }
+    _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.Decode" );
+    TUint8 dcs = KPhSrvUssdDefaultDCS;
+    if(aMsgAttributes.iFlags & RMobileUssdMessaging::KUssdMessageDcs)
+        {
+        dcs = aMsgAttributes.iDcs;
+        }
+    iDecodedMessage.Zero();
+    iReceivedMessage.Zero();
+    DecodeL(aMsgData, iDecodedMessage, dcs);
+    if(iDecodedMessage.Length() > 0)
+        {
+        iReceivedMessage = iDecodedMessage;
+        }
+    // 5. Show note.
+    // debug print
+    _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.Note" );
+    if ( !( aMsgAttributes.iFlags & RMobileUssdMessaging::KUssdMessageType ) ||
+            aMsgAttributes.iType != RMobileUssdMessaging::EUssdMTRequest )
+        {
+        if ( !ShowNotesL() )
+            {
+     
+            _DPRINT( 4,
+                "PhSrv.UssdHandleReceivedEventL.SAtReturn" );
+            return;
+            }
+        }
+
+    // empty string is handled as ok message
+    if ( !iDecodedMessage.Length() )
+        {
+        TurnLightsOn(); //Ensure lights on
+ 
+        _DPRINT( 4,
+            "PhSrv.UssdHandleReceivedEventL.EmptyString" );
+        
+        ShowDoneNoteL();
+
+ 
+        _DPRINT( 4,
+            "PhSrv.UssdHandleReceivedEventL.EmptyString.OK" );
+        }
+    else
+        {
+        _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.String" );
+        iNotifyMessage = ( aMsgAttributes.iType == RMobileUssdMessaging::EUssdMTNotify );
+        _DDPRINT( 4, "PhSrv.UssdHandleReceivedEventL.iNotifyMessage: ", iNotifyMessage );
+        _DDPRINT( 4, "PhSrv.UssdNOHREventL.iNotifyMessage: ", iNotifyMessage );
+        iMsgTypeReply = ( aMsgAttributes.iType == RMobileUssdMessaging::EUssdMTReply );
+        _DDPRINT( 4, "PhSrv.UssdHandleReceivedEventL.iMsgTypeReply: ", iMsgTypeReply );
+        
+        if ( iNotifyMessage ) 
+            {
+            // need to send an MO ack
+            iAcksToBeSent ++;
+            }
+        
+        if ( !iDeviceDialog  ){
+            iDeviceDialog = CHbDeviceMessageBoxSymbian::NewL(
+                CHbDeviceMessageBoxSymbian::EInformation );
+            iDeviceDialog->SetObserver( this );
+            iDeviceDialog->SetTimeout( KPhSrvUssdTimeout );
+            iDeviceDialog->SetDismissPolicy ( KPhSrvUssdPopupDismissPolicy );
+            
+            // Show left key with empty string accoring to ui concept
+            iDeviceDialog->SetButton( 
+                CHbDeviceMessageBoxSymbian::EAcceptButton, EFalse );
+            // Show Exit Key always
+            iDeviceDialog->SetButton( 
+                CHbDeviceMessageBoxSymbian::ERejectButton, ETrue );
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::ERejectButton, 
+                LoadDefaultString( KUssdExit ) );
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.Exit" );             
+        }
+      
+        if ( iNotifyMessage || iMsgTypeReply )
+            {
+            //This is for reply message in notifyarray
+            iNotifyMessage = ETrue;
+            _DDPRINT( 4, "PhSrv.UssdHandleReceivedEventL.iNotifyMessage: ", iNotifyMessage );
+
+            //Notify added to array
+            iNotifyArray->AppendL( iReceivedMessage );
+
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.AppendL" );
+            UpdateNotifyMessageL();
+
+            if ( !iSendRelease && NotifyCount() <= 1 )
+                {
+                _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.!SendRelease.Cancel" );
+                Cancel();
+                }
+            }
+        else
+            {
+            // New message deletes old message, i.e. Cancel existing query.
+            Cancel();
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.NewAnswerable" );
+            }
+
+        // Remove Reply key
+        if( !( aMsgAttributes.iFlags & RMobileUssdMessaging::KUssdMessageType )
+             || aMsgAttributes.iType != RMobileUssdMessaging::EUssdMTRequest )
+            {
+            // Remove Answer key
+            iDeviceDialog->SetButton( 
+                CHbDeviceMessageBoxSymbian::EAcceptButton, EFalse );
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.NoAnswer" ); 
+            }
+        // Show Reply key
+        else
+            {
+            iDeviceDialog->SetButton( 
+                CHbDeviceMessageBoxSymbian::EAcceptButton, ETrue );              
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, 
+                LoadDefaultString( KUssdReply ) ); 
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.WithAnswer" ); 
+            }
+
+ 
+        _DPRINT( 4,
+            "PhSrv.UssdHandleReceivedEventL.String.Middle" );
+
+        // Play the USSD tone if needed. Logically should be in RunL, but here
+        // to give better balancing with voice and visible message.
+        // <-- QT PHONE START-->
+        /*
+        if ( IsTelephonyFeatureSupported( KTelephonyLVFlagUssdTone ) )
+            {
+            _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.PlayTone" );
+            PlayUssdTone();
+            }
+        */
+            // <-- QT PHONE END-->
+        // Launch the new message query
+        if ( !IsActive() )
+            {
+            iLaunchGMQ = ETrue;
+            iTimer.After( iStatus , KPhSrvUssdMessageQueryInterval );
+            SetActive();
+            }
+        AsyncProcessMoAcks();
+        }
+    _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.Editor" );
+    if( aMsgAttributes.iType == RMobileUssdMessaging::EUssdMTRequest && UssdAppTaskExistsL() )
+        {
+        iEmptyEditor = ETrue;
+        }
+    _DPRINT( 4, "PhSrv.UssdHandleReceivedEventL.End" );
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::RestartReplyTimerL
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::RestartReplyTimerL()
+    {
+    if ( iUssdReplyTimer )
+        {
+        _DPRINT( 4, "PhSrv.RestartReplyTimerL.Stop" );
+        iUssdReplyTimer->Stop();
+        }
+
+    if ( !iUssdReplyTimer )
+        {
+        _DPRINT( 4, "PhSrv.RestartReplyTimerL.New" );
+        iUssdReplyTimer = CPhSrvUssdReplyTimer::NewL( *this );
+        }
+    
+    _DPRINT( 4, "PhSrv.RestartReplyTimerL.Start" );
+    iUssdReplyTimer->Start();
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdNetworkObserverHandleNotifyNWReleaseL
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::UssdNetworkObserverHandleNotifyNWReleaseL(
+const RMobilePhone::TMobilePhoneSendSSRequestV3 & aReturnResult,
+TInt aError )
+    {
+    _DDPRINT( 4, "PhSrv.UssdNotifyNWRelease ##### ", aError ); // debug print
+    _DPRINT_FLAGS();
+    TBool showNotes = ShowNotesL();
+    iNetworkReleased = ETrue;
+    iSendingAck = EFalse;
+    iSendRelease = EFalse;
+    iAcksToBeSent = 0;
+    
+    if ( iHavePendingSatMessagePointer )
+        {
+        iReturnResult = aReturnResult;
+        if ( !iSatCanceled )
+            {
+            CompleteSatL(&iReceivedMessage, aError );
+            _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleNotifyNWReleaseL.CompleteSat" );
+            }
+        }
+    if ( iUssdReplyTimer && iUssdReplyTimer->IsTimerActive() )
+        {
+        _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleNotifyNWReleaseL.Timer.Stop" );
+        iUssdReplyTimer->Stop();
+        Cancel();
+        CheckArray();
+        }
+    if ( showNotes && iShowDone )
+        {
+        ShowDoneNoteL();
+        }
+    if ( iUssdSendHandler && iSendingAck ) 
+        {
+        // if we are sending ack, it can be canceled.
+        iUssdSendHandler->Cancel();
+        }
+    
+    iSatCanceled = EFalse;
+    _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleNotifyNWReleaseL.iSatCanceled.EFalse" );
+    iShowDone = EFalse;
+    _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleNotifyNWReleaseL.Ending" );
+    _DPRINT_FLAGS();
+    _DPRINT( 4, "PhSrv.UssdNetworkObserverHandleNotifyNWReleaseL.End" );
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ShowDoneNoteL
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::ShowDoneNoteL()
+    {
+    _DDPRINT( 4, "PhSrv.ShowDoneNoteL.iShowDone", iShowDone );
+    // Show global confirmation note "Done"
+    CHbDeviceMessageBoxSymbian::InformationL(
+        LoadDefaultString( KUssdDone ) );
+    iShowDone = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ShowErrorNoteL
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::ShowErrorNoteL( TInt aError )
+    {
+    _DDPRINT( 4, "PhSrv.ShowErrorNoteL.Start ", aError );
+    if ( aError == KErrCancel )
+        {
+        _DPRINT( 4, "PhSrv.ShowErrorNoteL.Return" );
+        return;
+        }
+
+    // Show specific error message
+    CTextResolver* textResolver = CTextResolver::NewLC();
+    HBufC* buffer = textResolver->ResolveErrorString( aError ).AllocLC();
+
+    CHbDeviceMessageBoxSymbian::InformationL( buffer ->Des() );
+
+    CleanupStack::PopAndDestroy( buffer ); 
+    CleanupStack::PopAndDestroy( textResolver ); 
+    
+    
+    _DPRINT( 4, "PhSrv.ShowErrorNoteL.End" );
+    return;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::DecodeL
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::DecodeL(
+    const TDesC8& aSrc,
+    TDes& aDes ,
+    TUint8 aDcs )
+    {
+    _DPRINT( 4, "PhSrv.DecodeL.Start" );
+    aDes.Zero();
+    CCnvCharacterSetConverter* charConv = CCnvCharacterSetConverter::NewLC();
+
+    iDCS = KPhCltDcsUnknown; // default
+
+    // Check DCS
+    TSmsDataCodingScheme::TSmsAlphabet alphabet =
+        TSmsDataCodingScheme::ESmsAlphabet7Bit; // default
+    TUint cutChars = 0;
+    TUint startBit = 0;
+
+    // Codes from GSM 03.38
+    if ( aDcs == KPhSrvUssdDcsAlphabetDefaultPrecededLanguage )
+        {
+        FindFirstCarriageReturnL( aSrc , cutChars , startBit );
+        }
+    else if ( aDcs == KPhSrvUssdDcsAlphabetUCS2PrecededLanguage )
+        {
+        alphabet = TSmsDataCodingScheme::ESmsAlphabetUCS2;
+        cutChars = KPhSrvUssdDcsAlphabetUCS2PrecededLanguageSkipChars;
+        }
+    else if ( (aDcs&KPhSrvUssdDcsGeneralInformationMask)  ==
+            KPhSrvUssdDcsGeneralInformation ) // General data coding information
+        {
+        //Is text compressed?
+        if ( aDcs & KPhSrvUssdDcsGeneralInformationCompressed )
+            {
+            _DPRINT( 4, "PhSrv.DecodeL.KErrNotSupported" );
+            User::Leave( KErrNotSupported );
+            }
+        // Is SIM specific message
+        else if ( ( aDcs & KPhSrvUssdDcsGeneralInformationSimMask )
+                   == KPhSrvUssdDcsGeneralInformationSim )
+            {
+            _DPRINT( 4, "PhSrv.DecodeL.KErrAbort" );
+            User::Leave( KErrAbort ); // Do not show any messages
+            }
+        // 8 bit data?
+        else if ( ( aDcs&KPhSrvUssdDcsGeneralInformationAlphabetMask ) ==
+                   KPhSrvUssdDcsGeneralInformationAlphabet8Bit )
+            {
+            alphabet = TSmsDataCodingScheme::ESmsAlphabet8Bit;
+            }
+        // UCS2 bit data?
+        else if ( ( aDcs&KPhSrvUssdDcsGeneralInformationAlphabetMask ) ==
+                   KPhSrvUssdDcsGeneralInformationAlphabetUCS2 )
+            {
+            alphabet = TSmsDataCodingScheme::ESmsAlphabetUCS2;
+            }
+        }
+    // Data coding/message handling
+    else if ( ( aDcs & KPhSrvUssdDcsMessageHandlingAlphabetMask )
+               == KPhSrvUssdDcsMessageHandlingAlphabet8Bit )
+        {
+        alphabet = TSmsDataCodingScheme::ESmsAlphabet8Bit;
+        }
+
+    TPhSrvUssdAlphabetPacker* packer =
+        new ( ELeave ) TPhSrvUssdAlphabetPacker( alphabet , EFalse, startBit );
+    CleanupStack::PushL( packer );
+
+    if ( alphabet == TSmsDataCodingScheme::ESmsAlphabet7Bit )
+        {
+        TInt numberOfElem = ( ( aSrc.Length() - cutChars ) * 8 - startBit ) / 7;
+        packer->UnpackAndConvertL(
+            *charConv ,
+            iFsSession ,
+            aSrc.Right( aSrc.Length() - cutChars ),
+            aDes ,
+            numberOfElem );
+
+        // DCS was 7-bit data.
+        iDCS = KPhCltDcs7Bit;
+        }
+    else // ESmsAlphabet8Bit || ESmsAlphabetUCS2
+        {
+        CSmsAlphabetConverter* converter =
+            CSmsAlphabetConverter::NewLC(
+                *charConv , iFsSession,alphabet,EFalse );
+
+        aDes = converter->ConvertToNativeL(
+            aSrc.Right( aSrc.Length() - cutChars ) );
+        CleanupStack::PopAndDestroy( converter );
+
+        if( alphabet == TSmsDataCodingScheme::ESmsAlphabet8Bit )
+            {
+            // DCS was 8-bit data.
+            iDCS = KPhCltDcs8Bit;
+            }
+        else if( alphabet == TSmsDataCodingScheme::ESmsAlphabetUCS2 )
+            {
+            // DCS was UCS2 data.
+            iDCS = KPhCltDcsUcs2;
+            }
+        // If DCS not 8-bit or UCS2, then EPhCltDcsUnknown is returned.
+        }
+
+    //
+    CleanupStack::PopAndDestroy(2); // packer, charConv
+    _DPRINT( 4, "PhSrv.DecodeL.End" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::FindFirstCarriageReturnL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::FindFirstCarriageReturnL(
+    const TDesC8& aBuffer ,
+    TUint& aSkipChars ,
+    TUint& aStartBit )
+    {
+    _DPRINT( 4, "PhSrv.FindFirstCarriageReturnL.Start" );
+    if ( aBuffer.Length() < 3 )
+        {
+        _DPRINT( 4, "PhSrv.FindFirstCarriageReturnL.KErrUnderflow" );
+        User::Leave( KErrUnderflow );
+        }
+
+    aSkipChars = 0;
+    aStartBit = 0;
+
+    // Try out two different cases:
+    // 1. Find CR from thrid byte
+    // 2. Find CR from second byte, starting from bit 6
+
+    // 1.:
+    if ( aBuffer[2] == KPhSrvUssdCarriageReturn )
+        {
+        aSkipChars = KPhSrvUssdDcsAlphabetDefaultPrecededLanguageSkipChars3;
+        aStartBit = 0;
+        _DPRINT( 4, "PhSrv.FindFirstCarriageReturnL.ThirdByte.Return" );
+        return;
+        }
+
+    // 2.:
+    // First put the pieces together and then compare
+    // Take last 2 bits from the second byte:
+    TUint result1 = aBuffer[1];
+    result1 = result1 >> 6;
+
+    // Take first 5 bits from the third byte:
+    TUint result2 = aBuffer[2];
+    result2 = result2 & 0x1f; // bits 0-4.
+    result2 = result2 << 2; // move to bits 2-6.
+
+    TUint result = result1 + result2; // 0000 00xx + 0xxx xx00
+    if ( result == KPhSrvUssdCarriageReturn )
+        {
+        aSkipChars = KPhSrvUssdDcsAlphabetDefaultPrecededLanguageSkipChars2;
+        aStartBit = KPhSrvUssdDcsAlphabetDefaultPrecededLanguageStartBit;
+        _DPRINT( 4, "PhSrv.FindFirstCarriageReturnL.SecondByte.Return" );
+        return;
+        }
+
+    // Is was not case 1. or 2. so we are not supporting sort of string.
+    User::Leave( KErrNotSupported );
+    _DPRINT( 4, "PhSrv.FindFirstCarriageReturnL.KErrNotSupported" );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UssdReplyTimerObserverHandleExpired
+//
+//
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::UssdReplyTimerObserverHandleExpiredL( TInt aError )
+    {
+    _DDPRINT( 4, "PhSrv.ReplyTimer.Start.aError ", aError );     // debug print
+    delete iUssdReplyTimer;
+    iUssdReplyTimer = NULL;
+
+    if ( aError == KErrNone &&
+         IsActive() &&
+         iDeviceDialog ) 
+        {
+        Cancel();
+        // Terminates USSD session.
+        _DPRINT( 4, "PhSrv.ReplyTimer.SendRelease" );     // debug print
+        if ( iNotifyArray ) 
+            {
+            iNotifyArray->Reset();
+            }
+        TryCloseSession();
+        }
+    _DPRINT( 4, "PhSrv.ReplyTimer.End" );     // debug print
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::MessageBoxClosed
+// -----------------------------------------------------------------------------
+//       
+void CPhSrvUssdManager::MessageBoxClosed(
+    const CHbDeviceMessageBoxSymbian* aMessageBox,
+    CHbDeviceMessageBoxSymbian::TButtonId aButton)
+    {
+    _DPRINT( 4, "PhSrv.MsgClose.Start" );
+    // ussd device dialog observer callback function
+    TPtrC leftBtn = aMessageBox->ButtonText( 
+        CHbDeviceMessageBoxSymbian::EAcceptButton );
+    TPtrC rightBtn = aMessageBox->ButtonText( 
+        CHbDeviceMessageBoxSymbian::ERejectButton );    
+
+    TInt err = KErrNone;
+    // Click Yes on Confirmation note (Yes, No) 
+    if ( !leftBtn.Compare( 
+          LoadDefaultString( KUssdYes ) ) && 
+          ( CHbDeviceMessageBoxSymbian::EAcceptButton == aButton ) )
+        {
+        _DPRINT( 4, "PhSrv.MsgClose.SK.Yes" );
+        iClearArray = EFalse;
+        iNotifyArray->Reset();
+        TryCloseSession();
+        }
+    // Click "No" on Confirmation note (Yes, No) 
+    else if ( !rightBtn.Compare( 
+               LoadDefaultString( KUssdNo ) ) && 
+              ( CHbDeviceMessageBoxSymbian::ERejectButton == aButton ) )
+        {
+        _DPRINT( 4, "PhSrv.MsgClose.SK.No" );
+        iClearArray = EFalse;
+        iNotifyMessage = ETrue; // for removing the yes/no query
+        CheckArray();
+        TryCloseSession();
+        }
+    // Click "Next" on Notification note (Next, Exit) 
+    else if ( !leftBtn.Compare( 
+               LoadDefaultString( KUssdNext ) ) && 
+               ( CHbDeviceMessageBoxSymbian::EAcceptButton == aButton ) )
+        {
+        _DPRINT( 4, "PhSrv.MsgClose.SK.Next" ); 
+        CheckArray();
+        TryCloseSession();
+        }
+    // Click "Exit" on Notification note (Next, Exit or only Exit) 
+    else if ( !rightBtn.Compare( 
+               LoadDefaultString( KUssdExit ) ) && 
+               ( CHbDeviceMessageBoxSymbian::ERejectButton == aButton ) )
+        {
+        TRAP( err, ClearArrayL() );
+        _DDPRINT( 4, "PhSrv.MsgClose.SK.Clear.%d", err );
+        TryCloseSession();
+        _DPRINT( 4, "PhSrv.MsgClose.SK.Exit" ); 
+        }
+    // Click "Reply" on Message note (Reply, Exit) 
+    else if ( !leftBtn.Compare( 
+               LoadDefaultString( KUssdReply ) ) && 
+               ( CHbDeviceMessageBoxSymbian::EAcceptButton == aButton ) )
+        {
+        // Answer
+        iStartEditor = ETrue;
+        iShowDone = EFalse;
+        // Start the USSD editor now.
+        TRAP( err, RequestStartEditingL() );
+        _DDPRINT( 4, "PhSrv.MsgClose.RequestStartEditingL.%d", err );
+        }    
+    else 
+        {
+        _DPRINT( 4, "PhSrv.MsgClose.SK.Default" ); 
+        }
+  
+    _DPRINT( 4, "PhSrv.MsgClose.End" ); 
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::RunL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::RunL()
+    {
+    _DPRINT( 4, "PhSrv.RunL.Start" );    
+
+    ProcessMoAcksL();
+    
+    if ( iLaunchGMQ )
+        {
+        LaunchGlobalMessageQueryL();
+        // Do not launch Global Message Query next time.
+        iLaunchGMQ = EFalse;
+        _DPRINT( 4, "PhSrv.iLaunchGMQ.EFalse" );
+        }
+    else
+        {
+        iStartEditor = EFalse;
+        // update device dialog
+        _DPRINT( 4, "PhSrv.RunL.End" );     // debug print
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::LaunchGlobalMessageQueryL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::LaunchGlobalMessageQueryL()
+    {
+    _DPRINT( 4, "PhSrv.LGMQ.start" );
+    _DPRINT_FLAGS();
+
+    if ( iNotifyMessage )
+        {
+        _DDPRINT( 4, "PhSrv.LGMQ.NotifyMessage", iNotifyMessage );
+        iNotifyMessage = ETrue;
+        TInt count = NotifyCount();
+        //check softkey in avkon.rss 
+        if ( count > 1 )
+            {
+            // Next, Exit
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, ETrue );            
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, 
+                LoadDefaultString( KUssdNext ) );
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::ERejectButton, ETrue );    
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::ERejectButton, 
+                LoadDefaultString( KUssdExit ) );  
+            _DPRINT( 4, "PhSrv.LGMQ.Next&Exit" );
+            }
+        else
+            {
+            // Only Exit
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, EFalse ); 
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::ERejectButton, ETrue );               
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::ERejectButton, 
+                LoadDefaultString( KUssdExit ) );   
+            _DPRINT( 4, "PhSrv.LGMQ.onlyExit" );
+            }
+        if ( iClearArray )
+            {
+            HbTextResolverSymbian::Init( KCommonLocFilename, KLocPath );
+            _DPRINT( 4, "PhSrv.LGMQ.use common loc file" );
+            // Yes, No
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, ETrue );               
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::EAcceptButton, 
+                LoadDefaultString( KUssdYes ) );
+            iDeviceDialog->SetButton(
+                CHbDeviceMessageBoxSymbian::ERejectButton, ETrue );              
+            iDeviceDialog->SetButtonTextL(
+                CHbDeviceMessageBoxSymbian::ERejectButton, 
+                LoadDefaultString( KUssdNo ) );  
+            _DPRINT( 4, "PhSrv.LGMQ.Yes&No" );
+            HbTextResolverSymbian::Init( KUssdLocFilename, KLocPath );
+            _DPRINT( 4, "PhSrv.LGMQ.back up to use ussd loc file" );
+            }
+        iReceivedMessage.Zero();
+        iReceivedMessage = (*iNotifyArray)[0];
+        }
+    TurnLightsOn(); //Ensure lights on
+
+    _DPRINT( 4, "PhSrv.LGMQ.ShMsgQuery" ); // debug print
+    // Launch Global MessageQuery as requested.
+    // Dialog not support header text, this code is only 
+    // for testing, not final solution.
+    TInt receiveLength = iReceivedMessage.Length();
+    _DDPRINT( 4, "PhSrv.LGMQ.ShMsgQuery.MsgLength", receiveLength ); 
+    
+    TInt titleLength = LoadDefaultString( KUssdTitle ).Length();
+    _DDPRINT( 4, "PhSrv.LGMQ.ShMsgQuery.TilteLength", titleLength );
+    
+    TInt length = receiveLength + titleLength;
+    _DDPRINT( 4, "PhSrv.LGMQ.ShMsgQuery.TotalLength", length );    
+        
+    HBufC* titleAndText = HBufC::NewLC( length );
+    titleAndText->Des().Append( LoadDefaultString( KUssdTitle ) );
+    titleAndText->Des().Append( iReceivedMessage );
+    iDeviceDialog->SetTextL( titleAndText->Des() );
+    CleanupStack::Pop( titleAndText );
+    
+    iDeviceDialog->Close();
+    iDeviceDialog->ShowL();
+    iShowDone = EFalse;
+   
+    // Do nothing else in RunL this time.
+    _DPRINT( 4, "PhSrv.LGMQ.ShMsgQuery.ret" ); // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ProcessMoAcksL()
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::ProcessMoAcksL()
+    {
+    //Acknowledgment is sent if notify message
+    if ( iNotifyMessage && iAcksToBeSent )
+        {
+        _DPRINT( 4, "PhSrv.LGMQ.SendMoAcknowledgementL, start" );
+        _DPRINT_FLAGS();
+        if ( iUssdSendHandler && !iUssdSendHandler->IsActive() &&
+             !iNetworkReleased && !iSendRelease && !iSendingAck )
+            {
+            _DPRINT( 4, "PhSrv.LGMQ.MoAckNeededToBeSent" );
+            SendMoAcknowledgementL();
+            iAcksToBeSent--;
+            iSendingAck = ETrue;
+            }
+        _DPRINT( 4, "PhSrv.LGMQ.SendMoAcknowledgementL, end" );
+        }
+    }
+ 
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::AsyncProcessMoAcks()
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::AsyncProcessMoAcks()
+    {
+    if ( iMoAckCallback ) 
+        {
+        iMoAckCallback->CallBack();
+        _DPRINT( 4, "PhSrv.LGMQ.AsyncProcessMoAcksL, queued" );
+        }
+    }
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::MoAckCallback()
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager::MoAckCallback( TAny *aUssdManager )
+    {
+    _DPRINT( 4, "PhSrv.MoAckCallback.start" );
+    if ( aUssdManager )
+        {
+        CPhSrvUssdManager* manager = static_cast<CPhSrvUssdManager*>( aUssdManager );
+        TRAP_IGNORE( manager->ProcessMoAcksL() );
+        }
+    _DPRINT( 4, "PhSrv.MoAckCallback.end" );
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::TryCloseSession()
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::TryCloseSession() 
+    {
+    // Dismiss, cancel the session.
+    _DPRINT( 4, "PhSrv.CheckAndCloseSession.close" );  // debug print
+       
+    iShowDone = EFalse;
+    iEmptyEditor = EFalse;
+    
+    // If the notification array is empty, close the session.
+    if ( NotifyCount() == 0 && !iNetworkReleased )
+        {
+        CloseSession();
+        }
+    }
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::CloseSession()
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::CloseSession()
+    {
+    iSendRelease = ETrue;
+    iClearArray = EFalse;
+    iAcksToBeSent = 0;
+    _DPRINT( 4, "PhSrv.CheckAndCloseSession.canceling" ); 
+    SendUssdCancel();
+    Cancel();
+        
+    // Terminates USSD session.
+    if ( !iNetworkReleased ) 
+        {
+        iUssdSendHandler->SendReleaseSession();
+        }
+    if ( iUssdReplyTimer )
+        {
+        _DPRINT( 4, "PhSrv.CheckAndCloseSession.Timer.Stop" );
+        iUssdReplyTimer->Stop();
+        }
+    }
+ 
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::CheckArray()
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::CheckArray()
+    {
+    _DPRINT( 4, "PhSrv.CheckArray.Start" );     // debug print
+    if (iNotifyArray  && NotifyCount() > 0)
+        {
+        if  ( !iNotifyMessage && !iClearArray )
+            {
+            iLaunchGMQ = ETrue;
+            iNotifyMessage = ETrue;
+            _DPRINT( 4, "PhSrv.CheckArray.iNotifyMessage.ETrue" );
+            iTimer.After( iStatus , KPhSrvUssdMessageQueryInterval );
+            _DDPRINT( 4, "PhSrv.CheckArray.SetActive.NoNotifyMessage ", iStatus.Int() );
+            SetActive();
+            }
+        else if( NotifyCount() > 1 )
+            {
+            ( iNotifyArray )->Delete( 0 );
+            ( iNotifyArray )->Compress();
+            iLaunchGMQ = ETrue;
+            iNotifyMessage = ETrue;
+            _DPRINT( 4, "PhSrv.CheckArray.iNotifyMessage.ETrue" );
+            iTimer.After( iStatus , KPhSrvUssdMessageQueryInterval );
+            _DDPRINT( 4, "PhSrv.CheckArray.SetActive.NotifyCount>1 ", iStatus.Int() );
+            SetActive();
+            }
+        else
+            {
+            iNotifyArray->Reset();
+            iNotifyMessage = EFalse;
+            _DPRINT( 4, "PhSrv.CheckArray.iNotifyMessage.EFalse" );
+            }
+        }
+    _DPRINT_FLAGS();
+    _DPRINT( 4, "PhSrv.CheckArray.End" );     // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ClearArray()
+// -----------------------------------------------------------------------------
+//
+  void CPhSrvUssdManager::ClearArrayL()
+    {
+    _DPRINT( 4, "PhSrv.ClearArrayL.Start" );     // debug print
+    if (iNotifyArray && NotifyCount() > 0)
+        {
+        if (iNotifyMessage && NotifyCount()== 1 )
+            {
+            iNotifyArray->Reset();
+            }
+        else
+            {
+            iReceivedMessage.Zero();
+            iReceivedMessage.Append( 
+                LoadDefaultString( KUssdConfirm ) );
+            iNotifyArray->InsertL( 0, iReceivedMessage );
+            iLaunchGMQ = ETrue;
+            iNotifyMessage = ETrue;
+            _DPRINT( 4, "PhSrv.ClearArrayL.iNotifyMessage.ETrue" );
+            iClearArray = ETrue;
+            iTimer.After( iStatus , KPhSrvUssdMessageQueryInterval );
+            _DDPRINT( 4, "PhSrv.ClearArrayL.iTimer ", iStatus.Int() );
+            SetActive();
+            }
+        }
+    _DPRINT_FLAGS();
+    _DPRINT( 4, "PhSrv.ClearArrayL.End" );     // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::NotifyCount()
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager:: NotifyCount()
+{
+    TInt count = iNotifyArray->Count();
+    _DDPRINT( 4, "PhSrv.NotifyCount:", count );     // debug print
+    return count;
+}
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::UpdateNotifyMessageL()
+// -----------------------------------------------------------------------------
+//
+  void CPhSrvUssdManager:: UpdateNotifyMessageL()
+    {
+    _DDPRINT( 4, "PhSrv.UpdateNotifyMessageL.Start, clear: ", iClearArray );     // debug print
+
+    // Show left softkey - "Next"
+    if (NotifyCount() > 1 && !iClearArray )
+        {
+        _DPRINT( 4, "PhSrv.UpdateNotifyMessageL" );     // debug print
+        iDeviceDialog->SetButton( 
+            CHbDeviceMessageBoxSymbian::EAcceptButton, ETrue ); 
+        iDeviceDialog->SetButtonTextL(
+            CHbDeviceMessageBoxSymbian::EAcceptButton, 
+            LoadDefaultString( KUssdNext ) );
+        }
+    // Remove left softkey
+    else
+        {
+        iDeviceDialog->SetButton( 
+                    CHbDeviceMessageBoxSymbian::EAcceptButton, EFalse );         
+        }
+    iDeviceDialog->UpdateL();        
+    
+    _DPRINT( 4, "PhSrv.UpdateNotifyMessageL.End" );     // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::DoCancel()
+    {
+    _DPRINT( 4, "PhSrv.DoCancel.Start" ); // debug print
+    iTimer.Cancel();
+    iLaunchGMQ = EFalse;
+    if ( iDeviceDialog )
+        {
+        _DPRINT( 4, "PhSrv.DoCancel" ); // debug print
+        iDeviceDialog->Close();
+        delete iDeviceDialog;
+        iDeviceDialog = NULL;
+        }
+    _DPRINT( 4, "PhSrv.DoCancel.End" ); // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::RunError
+//
+// Because the RunL can leave, this function exists.
+// In case of error, just returning KErrNone is OK.
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager::RunError( TInt /*aError*/ )
+    {
+    _DPRINT( 4, "PhSrv.RunError.Start" );     // debug print
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::RequestStartEditingL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::RequestStartEditingL()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.RequestStartEditingL.start" ); // debug print
+
+    RWsSession wsSession;
+    User::LeaveIfError( wsSession.Connect() );
+    _DPRINT( 4, "PhSrv.RequestStartEditingL.wsSession.connect" );     // debug print
+    CleanupClosePushL( wsSession );
+
+    // Find the task with name
+    TApaTaskList tasklist( wsSession );
+    TApaTask task = tasklist.FindApp( KUssdSecureId );
+
+    // If task exists, bring it to foreground
+    if ( task.Exists() )
+        {
+        _DPRINT( 4, "PhSrv.UssdM.RequestStartEditingL.task.BringToForeground" );
+        task.BringToForeground();
+        }
+    else
+        {
+        // Start new app
+        RApaLsSession apaLsSession;
+        User::LeaveIfError( apaLsSession.Connect() );
+        _DPRINT( 4, "PhSrv.RequestStartEditingL.apaLsSession.connect" );     // debug print
+        CleanupClosePushL( apaLsSession );
+
+        TApaAppInfo appInfo;
+        
+        TInt err = apaLsSession.GetAppInfo( appInfo, KUssdSecureId );
+        _DDPRINT( 4, "PhSrv.RequestStartEditingL.GetAppInfo ", err );     // debug print
+        
+        if ( err == KErrNone )
+            {
+        #ifndef SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+            CApaCommandLine* apaCommandLine = CApaCommandLine::NewLC();
+            apaCommandLine->SetExecutableNameL( appInfo.iFullName );
+        #else // SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+            CApaCommandLine* apaCommandLine =
+                CApaCommandLine::NewLC( appInfo.iFullName );
+        #endif // SYMBIAN_SUPPORT_UI_FRAMEWORKS_V1
+
+            TThreadId id( static_cast<TInt64>( 0 ) );
+            err = apaLsSession.StartApp( *apaCommandLine, id );
+            _DDPRINT( 4, "PhSrv.RequestStartEditingL.ThreadId ", id ); 
+            CleanupStack::PopAndDestroy( apaCommandLine );
+            }
+        CleanupStack::PopAndDestroy( &apaLsSession ); // apaLsSession
+        
+        // bring the ussd editor to foreground, only for testing
+        TApaTaskList tasklist( wsSession );
+        TApaTask task = tasklist.FindApp( KUssdSecureId );
+        if ( task.Exists() )
+            {
+            _DPRINT( 4, "PhSrv.UssdM.RequestStartEditingL.task.BringToForeground" );
+            task.BringToForeground();
+            }
+        // bring the ussd editor to foreground, only for testing
+        }
+    CleanupStack::PopAndDestroy(); // wsSession
+
+    _DPRINT( 4, "PhSrv.UssdM.RequestStartEditingL.end" ); // debug print
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformUssdApplicationStarting
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::InformUssdApplicationStarting()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppStarting.start" ); // debug print
+    if ( iUssdReplyTimer )
+        {
+        _DPRINT( 4, "PhSrv.InformUssdApplicationStarting.iUssdReplyTimer" );
+        if ( iUssdReplyTimer->IsTimerActive() )
+            {
+            _DPRINT( 4, "PhSrv.InformUssdApplicationStarting.iUssdReplyTimer.active" );
+            iUssdReplyTimer->Pause();
+            }
+        }
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppStarting.end" ); // debug print
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformUssdApplicationTerminatingL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::InformUssdApplicationTerminatingL(
+    const RMessage2& aMessage )
+    {
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppTerminatingL.start" ); // debug print
+    if ( iUssdReplyTimer )
+        {
+        if ( iUssdReplyTimer->IsTimerActive() )
+            {
+     
+            _DPRINT( 4, "PhSrv.UssdM.InfUssdAppTerminatingL.timer" );
+
+            // Read the information what is the reason
+            // for application termination.
+            TPhCltUssdAppExitReason exitReason = EPhCltExitReasonUnknown;
+            TPckg< TPhCltUssdAppExitReason > exitReasonPckg( exitReason );
+            aMessage.ReadL(
+                0,
+                exitReasonPckg );
+
+     
+            _DPRINT( 4, "PhSrv.UssdM.InfUssdAppTerminatingL.timer2" );
+
+            // If reason was the completion of send operation, the USSD
+            // session is not canceled, otherwise it is canceled.
+            if ( exitReason != EPhCltSendCompleted )
+                {
+         
+                _DPRINT( 4, "PhSrv.UssdM.InfUssdAppTerminatingL.SendRelease" );
+                CloseSession();
+                }
+            }
+        }
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppTerminatingL.end" ); // debug print
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformUssdApplicationToForeground
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager::InformUssdApplicationToForeground()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToForeground.start" ); // debug print
+
+    // Do the same actions as in InformUssdApplicationStarting,
+    // that is why it is called.
+    InformUssdApplicationStarting();
+
+    if ( iEmptyEditor )
+        {
+        _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToForeground.empty" ); // debug print
+        iEmptyEditor = EFalse;
+        return 1; // some positive number
+        }
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToForeground.end" ); // debug print
+    return KErrNone;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformUssdApplicationToBackground
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::InformUssdApplicationToBackground()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToBackground.start" ); // debug print
+    if ( iUssdReplyTimer )
+        {
+        _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToBackground.timer" ); // debug print
+        if ( iUssdReplyTimer->IsTimerActive() )
+            {
+            _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToBackground.timer.Active" ); // debug print
+            iUssdReplyTimer->Continue();
+            }
+        }
+    _DPRINT( 4, "PhSrv.UssdM.InfUssdAppToBackground.end" ); // debug print
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformStartSAT
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::InformStartSAT( const RMessage2& aSatMessage )
+    {
+    _DPRINT( 4, "PhSrv.InformStartSAT.Start" );    // debug print
+
+    if ( iHavePendingSatMessagePointer )
+        {
+        _DPRINT( 4, "PhSrv.InformStartSAT.Complete.InUse" ); // debug print
+        aSatMessage.Complete( KErrInUse );
+        }
+    else
+        {
+        _DPRINT( 4, "PhSrv.InformStartSAT.Set" );    
+
+        // There was not pending SAT message
+        iHavePendingSatMessagePointer = ETrue;
+        _DDPRINT( 4, "PhSrv.UssdM.InformStartSAT.PendingSatPointer ", iHavePendingSatMessagePointer );
+        iPendingSatMessagePointer = aSatMessage;
+        }
+
+    _DPRINT( 4, "PhSrv.InformStartSAT.End" );   // debug print
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::InformStopSAT
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::InformStopSAT()
+    {
+    _DPRINT( 4, "PhSrv.InformStopSAT.Start" );        
+
+    // Do the actions only if there is pending SAT message.
+    if ( iHavePendingSatMessagePointer )
+        {
+        _DPRINT( 4, "PhSrv.InformStopSAT.Complete.Cancel" ); // debug print
+        if ( !iPendingSatMessagePointer.IsNull() )
+            {
+            iPendingSatMessagePointer.Complete( KErrCancel );
+            _DPRINT( 4, "PhSrv.InformStopSAT.Complete.KErrCancel" );
+            }
+        iHavePendingSatMessagePointer = EFalse;
+        }
+    _DPRINT( 4, "PhSrv.InformStopSAT.End" );          
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::ShowNotes
+// -----------------------------------------------------------------------------
+//
+
+
+TBool CPhSrvUssdManager::ShowNotesL()
+{
+_DPRINT( 4, "PhSrv.ShowNotesL.Start" );
+
+if ( !iHavePendingSatMessagePointer )
+    {
+    if ( iSatCanceled )
+        {
+        _DPRINT( 4, "PhSrv.ShowNotesL, EFalse" );  // debug print
+        return EFalse;
+        }
+    else
+        {
+        _DPRINT( 4, "PhSrv.ShowNotesL, ETrue" );  // debug print
+        return ETrue;
+        }
+    }
+// Read the information whether the notes are shown or not.
+    TUint notesShown = 0;
+    TPckg< TUint > noShPckg( notesShown );
+    iPendingSatMessagePointer.ReadL(
+        0,
+        noShPckg );
+
+    TBool showNotes = EFalse;
+    _DPRINT( 4, "PhSrv.ShowNotes Sat= EFalse" );    // debug print
+    if ( notesShown == KPhCltShowNotes )
+        {
+        _DPRINT( 4, "PhSrv.ShowNotes Sat= ETrue" ); // debug print
+        showNotes = ETrue;
+        }
+    _DPRINT( 4, "PhSrv.ShowNotesL.End" );
+    return showNotes;
+}
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::CompleteSatL
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::CompleteSatL(
+    TDesC* aReceiveString,
+    TInt aError )
+    {
+    _DPRINT( 4, "PhSrv.CompleteSatL.Start" );         
+    if ( aReceiveString )
+        {
+        if ( aReceiveString->Length() )
+            {
+            _DPRINT( 4, "PhSrv.CompleteSatL.recString.>0" ); // debug print
+            // copy the received string to client side.
+            if ( iPendingSatMessagePointer.Int1() < aReceiveString->Length() )
+                {
+         
+                _DPRINT( 4, "PhSrv.CompleteSatL.recString.LengthError" );
+                if ( !iPendingSatMessagePointer.IsNull() )
+                    {
+                    iPendingSatMessagePointer.Complete( KErrOverflow );
+                    _DPRINT( 4, "PhSrv.CompleteSatLComplete.KErrOverFlow" );
+                    }
+                iHavePendingSatMessagePointer = EFalse;
+                }
+            else
+                {
+            _DPRINT( 4, "PhSrv.CompleteSatL.recString.Write" );  // debug print
+            iPendingSatMessagePointer.WriteL(
+                2,
+                *aReceiveString );
+
+            _DPRINT( 4, "PhSrv.CompleteSatL.recString.Write2" ); // debug print
+            TPckg< TUint > dcsPackage( iDCS );
+            iPendingSatMessagePointer.WriteL(
+                0,
+                dcsPackage );
+            }
+        }
+        }
+    _DPRINT( 4, "PhSrv.CompleteSatL.Middle" );    
+    if ( !iPendingSatMessagePointer.IsNull() )
+        {
+        if ( aReceiveString && !iSatCanceled )
+            {
+            _DDPRINT( 4, "PhSrv.CompleteSatL.Complete.", iReturnResult.iOpCode  );   // debug print
+            iPendingSatMessagePointer.Complete( iReturnResult.iOpCode ); // Some positive value
+            }
+        else
+            {
+            _DPRINT( 4, "PhSrv.CompleteSatL.Complete.aError" ); // debug print
+            iPendingSatMessagePointer.Complete( aError );
+            }
+        }
+
+    iHavePendingSatMessagePointer = EFalse;
+
+    _DPRINT( 4, "PhSrv.CompleteSatL.End" );    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::IsTelephonyFeatureSupported
+//
+// -----------------------------------------------------------------------------
+//
+TBool CPhSrvUssdManager::IsTelephonyFeatureSupported(
+    const TInt aFeatureId )
+    {
+    return ( aFeatureId & iVariantReadOnlyValues );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::PlayUssdTone
+//
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager::PlayUssdTone()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.PlayTone.start" );    
+
+    TInt err = KErrNone;
+// <-- QT PHONE  START-->
+//    RProperty::Define( KPSUidNcnList, KNcnPlayAlertTone, RProperty::EInt, ECapability_None , ECapabilityWriteDeviceData );
+//    RProperty::Set( KPSUidNcnList, KNcnPlayAlertTone, KPhSrvUssdTone );
+// <-- QT PHONE END-->
+
+    // debug print
+    _DDPRINT(
+        4,
+        "PhSrv.UssdM.PlayTone.end",
+        err );
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::GetTelephonyVariantData
+//
+// -----------------------------------------------------------------------------
+//
+TInt CPhSrvUssdManager::GetTelephonyVariantData()
+    {
+    _DPRINT( 4, "PhSrv.UssdM.GetTelephonyVariantData.Start" );
+    TInt err = KErrNone;
+// <-- QT PHONE START-->
+/*
+    // Variation data should be unchangable during run-time,
+    // therefore, if once succesfully read, later reads are
+    // not allowed.
+    if ( iVariantReadOnlyValues == KPhSrvDefaultValue )
+        {
+        CRepository* cenRepSession = NULL;
+        TRAP ( err ,
+               cenRepSession = CRepository::NewL( KCRUidTelVariation ) );
+        if ( err == KErrNone )
+            {
+            err = cenRepSession->Get( KTelVariationFlags,
+                                   iVariantReadOnlyValues );
+            }
+        delete cenRepSession;
+        }
+
+    _DDPRINT( 4, "PhSrv.UssdM.variant", iVariantReadOnlyValues ); // debug print
+    _DPRINT( 4, "PhSrv.UssdM.GetTelephonyVariantData.End" );
+    */
+// <-- QT PHONE END-->
+    return err;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::SendMoAcknowledgementL
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::SendMoAcknowledgementL()
+    {
+    _DPRINT( 4, "PhSrv.SendMoAckL.Start" );    
+
+    // Acknowledge MT USSD message.
+    RMobileUssdMessaging::TMobileUssdAttributesV1 msgAttribs;
+    msgAttribs.iFlags =
+        RMobileUssdMessaging::KUssdMessageType +
+        RMobileUssdMessaging::KUssdDataFormat  +
+        RMobileUssdMessaging::KUssdMessageDcs;
+
+    msgAttribs.iType   = RMobileUssdMessaging::EUssdMOAcknowledgement;
+    _DDPRINT( 4, "PhSrv.SendMoAckL.msgAttribs.iType ", msgAttribs.iType );
+    msgAttribs.iFormat = RMobileUssdMessaging::EFormatUnspecified;
+    _DDPRINT( 4, "PhSrv.SendMoAckL.msgAttribs.iFormat ", msgAttribs.iFormat );
+    msgAttribs.iDcs    = KPhSrvUssdDefaultDCS;
+
+    RMobileUssdMessaging::TMobileUssdAttributesV1Pckg attribs = msgAttribs;
+    SendHandlerL().SendUssdL( KNullDesC8() , attribs );
+
+    _DPRINT( 4, "PhSrv.SendMoAckL.End" );    
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::TurnLightsOn
+//
+// -----------------------------------------------------------------------------
+//
+void CPhSrvUssdManager::TurnLightsOn()
+    {
+    _DPRINT( 4, "PhSrv.TurnLightsOn.Start" );    
+
+
+     // Change the bit on and off. SysAp will detect that
+     // the lights should be switched on for the specified time.
+     //
+     RProperty::Set(KPSUidCoreApplicationUIs, KLightsControl, ELightsOn);
+     TInt err = RProperty::Set(KPSUidCoreApplicationUIs, KLightsControl, ELightsOff);
+
+     if ( err != KErrNone )
+         {
+         _DDPRINT( 4,"PhSrv.TurnLightsOn.Error: ",err );// debug print
+         }
+
+    _DPRINT( 4, "PhSrv.TurnLightsOn.End" );    
+    }
+
+// -----------------------------------------------------------------------------
+// CPhSrvUssdManager::LoadDefaultString
+// -----------------------------------------------------------------------------
+//
+const TPtrC CPhSrvUssdManager::LoadDefaultString( const TDesC& aText )
+    {
+    _DPRINT( 4, "PhSrv.LoadDefaultString.Start" );
+    
+    if ( iTextBuffer )
+        {
+        delete iTextBuffer;
+        iTextBuffer = NULL;
+        _DPRINT( 4, "PhSrv.LoadDefaultString.Clear" );
+        }
+    TInt err = KErrNone;
+    TPtrC ptr( aText );
+    if ( ptr.Length() )
+        {
+        TRAP( err, iTextBuffer = HbTextResolverSymbian::LoadL( ptr ) );
+        _DDPRINT( 4, "PhSrv.LoadDefaultString.LoadL.%d", err );
+        if ( iTextBuffer )
+            {
+            ptr.Set( iTextBuffer->Des() );   
+            _DPRINT( 4, "PhSrv.LoadDefaultString.Set" );
+            }
+        }    
+    _DPRINT( 4, "PhSrv.LoadDefaultString.End" );
+    return ptr;
+    }
+
+// End of File