diff -r 8ca85d2f0db7 -r aabf2c525e0f uifw/AvKon/src/AknEcs.cpp --- a/uifw/AvKon/src/AknEcs.cpp Fri Feb 19 23:04:46 2010 +0200 +++ b/uifw/AvKon/src/AknEcs.cpp Fri Mar 12 15:43:43 2010 +0200 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). +* 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" @@ -35,9 +35,16 @@ #include #include #include +#include +#include +#include +#include #include "akntrace.h" +const TInt KAknKeyScanCodeBegin = 33; +const TInt KAknKeyScanCodeEnd = 126; + // CLASS DECLARATIONS /** Class for getting emergency call events */ @@ -98,13 +105,17 @@ enum TStatus { ENoMatch, - ECompleteMatch + ECompleteMatch, + EServiceNumMatch }; public: /** * C++ constructor + * + * @param aPhCltEmergencyCall Emergency call client + * @param aServiceCallEnabled Is service call feature enabled during device or key lock. */ - CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall ); + CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled ); /** * C++ destructor @@ -173,6 +184,15 @@ */ TInt IndexOfCurrentMatch() const; + /** + * Validates the service number. + * + * @param aNumber Service number to be validated from CenRep. + * + * @return Returns ETrue if aNumber is a service number, EFalse if not. + */ + TBool ValidateServiceNumberL( const TDesC& aNumber ); + private: /** * Update the status of the queue @@ -187,6 +207,7 @@ CPhCltEmergencyCall* iPhCltEmergencyCall; TStatus iStatus; // Holds the status; TInt iMatchPosition; // Position in iCharBuffer from where the match starts. + TBool iServiceCallFeature; // True if service call feature is enabled. TAny* iSpare; }; @@ -218,8 +239,8 @@ // -CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall ) - : iPhCltEmergencyCall( aPhCltEmergencyCall ) +CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled ) + : iPhCltEmergencyCall( aPhCltEmergencyCall ), iServiceCallFeature( aServiceCallEnabled ) { _AKNTRACE_FUNC_ENTER; Reset(); @@ -256,7 +277,7 @@ } iCharBuffer.Append( aNewChar ); UpdateStatus( EFalse ); - _AKNTRACE_FUNC_ENTER; + _AKNTRACE_FUNC_EXIT; } void CAknMatchingCharacterQueue::SetBuffer( const TDesC& aNewBuffer ) @@ -324,17 +345,65 @@ iMatchPosition = cbLength - bLength; iStatus = ECompleteMatch; } + else if ( iServiceCallFeature && cbLength >= KAknServiceCallMinLength ) + { + // Check if this is a service call + TBool isServiceNum = EFalse; + TRAP_IGNORE( isServiceNum = ValidateServiceNumberL( iCharBuffer ) ); + + if ( isServiceNum ) + { + iMatchPosition = 0; + iStatus = EServiceNumMatch; + } + else + { + iMatchPosition = cbLength; + iStatus = ENoMatch; + } + } else { iMatchPosition = cbLength; iStatus = ENoMatch; } - _AKNTRACE( "[%s][%s] iStatus: %d", "CAknMatchingCharacterQueue", __FUNCTION__,iStatus ); _AKNTRACE_FUNC_EXIT; } +// ----------------------------------------------------------------------------- +// CAknMatchingCharacterQueue::ValidateServiceNumber +// +// Validates the service phone number. +// ----------------------------------------------------------------------------- +// +TBool CAknMatchingCharacterQueue::ValidateServiceNumberL( const TDesC& aNumber ) + { + _AKNTRACE_FUNC_ENTER; + TBool isServiceNum = EFalse; + HBufC* serviceNum = HBufC::NewLC( KAknEcsMaxMatchingLength ); + CRepository* cenRep = CRepository::NewLC( KCRUidAvkon ); + TPtr bufPtr = serviceNum->Des(); + + if( cenRep->Get( KAknServiceCallNumber, bufPtr ) != KErrNone ) + { + CleanupStack::PopAndDestroy( cenRep ); + CleanupStack::PopAndDestroy( serviceNum ); + return EFalse; + } + + // Check if aNumber matches serviceNum + if ( aNumber.Compare( *serviceNum ) == 0 ) + { + isServiceNum = ETrue; + } + + CleanupStack::PopAndDestroy( cenRep ); + CleanupStack::PopAndDestroy( serviceNum ); + _AKNTRACE_FUNC_EXIT; + return isServiceNum; + } // // @@ -370,7 +439,12 @@ iEmergencyCallObserver = new (ELeave) CPhCltEmergencyCallObserver( this ); // Phone client interface iPhCltEmergencyCall = CPhCltEmergencyCall::NewL( iEmergencyCallObserver ); - iQueue = new (ELeave) CAknMatchingCharacterQueue(iPhCltEmergencyCall); + + // Check if service call is allowed during device and key lock + iServiceCallEnabled = + FeatureManager::FeatureSupported( KFeatureIdFfServiceCallWhilePhoneLocked ); + + iQueue = new (ELeave) CAknMatchingCharacterQueue( iPhCltEmergencyCall, iServiceCallEnabled ); iQueue->ConstructL(); DetermineState(); @@ -423,14 +497,24 @@ _AKNTRACE_FUNC_ENTER; _AKNTRACE( "[%s][%s] aEvent.type(): %d, aEvent.Key()->iScanCode :%d", "CAknEcsDetector", __FUNCTION__,aEvent.Type(),aEvent.Key()->iScanCode ); - if ( aEvent.Type() == EEventKeyDown || - // EKeyPhoneEnd/EKeyNo doesn't send EEVentKeyDown events, so EEventKey is used instead - ( ( aEvent.Key()->iScanCode == EStdKeyNo ) && ( aEvent.Type() == EEventKey ) ) - ) + // EKeyPhoneEnd/EKeyNo doesn't send EEVentKeyDown events, so EEventKey is used instead + ( ( aEvent.Key()->iScanCode == EStdKeyNo ) && ( aEvent.Type() == EEventKey ) ) ) { AddChar( (TText)(aEvent.Key()->iScanCode ) ); // top 16 ( in Unicode build) bits removed - } + } + + if ( iServiceCallEnabled ) + { + // When Cancel is pressed we need to clear the queue + if ( iState == EServiceNumMatch && aEvent.Type() == EEventPointer && + aEvent.Pointer()->iType == TPointerEvent::EButton1Down ) + { + // Clear the queue, set state to EEmpty, and cancel any pending timeout + Reset(); + iKeyTimeoutTimer->Cancel(); + } + } _AKNTRACE_FUNC_EXIT; } @@ -440,27 +524,46 @@ _AKNTRACE_FUNC_ENTER; _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknEcsDetector", __FUNCTION__, &aNewChar ); - + if (aNewChar == EKeyQwertyOn || aNewChar == EKeyQwertyOff) - { + { _AKNTRACE_FUNC_EXIT; - return; // return directly if the aNewChar is slide open/closed. - } - + return; // return directly if the aNewChar is slide open/closed. + } + iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it - if ( aNewChar == EStdKeyYes || aNewChar ==EKeyPhoneSend ) + if ( aNewChar == EStdKeyYes || aNewChar == EKeyPhoneSend ) { - if ( State() == ECompleteMatch ) + if ( iServiceCallEnabled ) { - _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", - __FUNCTION__ ); - SetState( ECompleteMatchThenSendKey ); + if ( iState == ECompleteMatch || iState == EServiceNumMatch ) + { + _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", + __FUNCTION__ ); + SetState( ECompleteMatchThenSendKey ); + } + } + else + { + if ( iState == ECompleteMatch ) + { + _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", + __FUNCTION__ ); + SetState( ECompleteMatchThenSendKey ); + } } // else do nothing with it... } else { TText scanCode = aNewChar; + + if ( scanCode < KAknKeyScanCodeBegin || scanCode > KAknKeyScanCodeEnd ) + { + // Just return since it is an invalid character + return; + } + #ifdef RD_INTELLIGENT_TEXT_INPUT // Convert scan code to number value here // for 4*10, 3*11, half-qwerty key pad @@ -588,6 +691,13 @@ case CAknMatchingCharacterQueue::ECompleteMatch: bestState = ECompleteMatch; break; + case CAknMatchingCharacterQueue::EServiceNumMatch: + if ( iServiceCallEnabled ) + { + bestState = EServiceNumMatch; + break; + } + // Fall through to default case if service call feature is off default: __ASSERT_DEBUG( 0, Panic(EAknEcsPanicBadState) ); break; @@ -632,12 +742,24 @@ iQueue->Reset(); iQueue->SetBuffer(aNewBuffer); DetermineState(); - if ( State() == ECompleteMatch ) + + if ( iServiceCallEnabled ) { - _AKNTRACE( "[%s][%s] State() == ECompleteMatch ", "CAknEcsDetector", - __FUNCTION__ ); - iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, - KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); + if ( iState == ECompleteMatch || iState == EServiceNumMatch ) + { + iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, + KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); + } + } + else + { + if ( iState == ECompleteMatch ) + { + _AKNTRACE( "[%s][%s] State() == ECompleteMatch ", "CAknEcsDetector", + __FUNCTION__ ); + iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, + KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); + } } _AKNTRACE_FUNC_EXIT; } @@ -684,6 +806,19 @@ } break; + case EServiceNumMatch: + if ( iServiceCallEnabled ) + { + if ( aNewState == ECompleteMatchThenSendKey ) + { + RelinquishCapturedKeys(); + _AKNTRACE( "[%s][%s] Make Service Call", "CAknEcsDetector", + __FUNCTION__); + TRAP_IGNORE( MakeServiceCallL() ); + } + } + break; + default: break; @@ -738,6 +873,51 @@ _AKNTRACE_FUNC_EXIT; } +void CAknEcsDetector::MakeServiceCallL() + { + _AKNTRACE_FUNC_ENTER; + if ( iServiceCallEnabled ) + { + CAiwServiceHandler* aiwServiceHandler = CAiwServiceHandler::NewLC(); + RCriteriaArray interest; + CleanupClosePushL( interest ); + + CAiwCriteriaItem* criteria = CAiwCriteriaItem::NewLC( KAiwCmdCall, + KAiwCmdCall, _L8( "*" ) ); + TUid base; + base.iUid = KAiwClassBase; + criteria->SetServiceClass( base ); + User::LeaveIfError( interest.Append( criteria ) ); + aiwServiceHandler->AttachL( interest ); + + CAiwDialData* dialData = CAiwDialData::NewLC(); + dialData->SetCallType( CAiwDialData::EAIWForcedCS ); + dialData->SetPhoneNumberL( CurrentMatch() ); + dialData->SetWindowGroup( AIWDialData::KAiwGoToIdle ); + + CAiwGenericParamList& paramList = aiwServiceHandler->InParamListL(); + dialData->FillInParamListL( paramList ); + + TRAPD( err, aiwServiceHandler->ExecuteServiceCmdL( KAiwCmdCall, paramList, + aiwServiceHandler->OutParamListL(), 0, NULL ) ); + __ASSERT_DEBUG( err == KErrNone, Panic( EAknEcsPanicDialLLeft ) ); + + //reset the queue + iQueue->Reset(); + + CleanupStack::PopAndDestroy( dialData ); + CleanupStack::PopAndDestroy( criteria ); + CleanupStack::PopAndDestroy( &interest ); + CleanupStack::PopAndDestroy( aiwServiceHandler ); + + if( err != KErrNone ) + { + User::Leave( err ); + } + } + _AKNTRACE_FUNC_EXIT; + } + EXPORT_C void CAknEcsDetector::SetObserver( MAknEcsObserver* aObserver ) { iObserver = aObserver;