--- a/uifw/AvKon/src/AknEcs.cpp Tue Aug 31 15:28:30 2010 +0300
+++ b/uifw/AvKon/src/AknEcs.cpp Wed Sep 01 12:16:19 2010 +0100
@@ -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"
@@ -29,13 +29,21 @@
#include <featmgr.h>
#include "AknDebug.h"
-#include <cphcltemergencycall.h>
-#include <mphcltemergencycallobserver.h>
-#include <phclttypes.h>
+#include <CPhCltEmergencyCall.h>
+#include <MPhCltEmergencyCallObserver.h>
+#include <PhCltTypes.h>
#include <AvkonInternalCRKeys.h>
#include <PtiDefs.h>
#include <e32property.h>
+#include <AiwCommon.hrh>
+#include <aiwdialdata.h>
+#include <AiwServiceHandler.h>
+#include <centralrepository.h>
+#include "akntrace.h"
+
+const TInt KAknKeyScanCodeBegin = 33;
+const TInt KAknKeyScanCodeEnd = 126;
// CLASS DECLARATIONS
@@ -97,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
@@ -172,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
@@ -186,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;
};
@@ -217,10 +239,12 @@
//
-CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall )
- : iPhCltEmergencyCall( aPhCltEmergencyCall )
+CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled )
+ : iPhCltEmergencyCall( aPhCltEmergencyCall ), iServiceCallFeature( aServiceCallEnabled )
{
+ _AKNTRACE_FUNC_ENTER;
Reset();
+ _AKNTRACE_FUNC_EXIT;
}
CAknMatchingCharacterQueue::~CAknMatchingCharacterQueue( )
@@ -233,12 +257,18 @@
void CAknMatchingCharacterQueue::Reset()
{
+ _AKNTRACE_FUNC_ENTER;
iMatchPosition = 0;
iCharBuffer.Zero();
+ _AKNTRACE_FUNC_EXIT;
}
void CAknMatchingCharacterQueue::AddChar( TText aNewChar )
{
+ _AKNTRACE_FUNC_ENTER;
+ _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknMatchingCharacterQueue",
+ __FUNCTION__,&aNewChar);
+
TInt length = iCharBuffer.Length();
TInt maxLenght = iCharBuffer.MaxLength();
if (length >= maxLenght)
@@ -247,10 +277,15 @@
}
iCharBuffer.Append( aNewChar );
UpdateStatus( EFalse );
+ _AKNTRACE_FUNC_EXIT;
}
void CAknMatchingCharacterQueue::SetBuffer( const TDesC& aNewBuffer )
{
+ _AKNTRACE_FUNC_ENTER;
+ _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknMatchingCharacterQueue",
+ __FUNCTION__,&aNewBuffer);
+
TInt maxLenght = iCharBuffer.MaxLength();
TInt length = aNewBuffer.Length();
if ( length > maxLenght )
@@ -259,6 +294,7 @@
}
iCharBuffer = aNewBuffer.Left( length );
UpdateStatus( ETrue );
+ _AKNTRACE_FUNC_EXIT;
}
TInt CAknMatchingCharacterQueue::Count() const
@@ -283,6 +319,7 @@
void CAknMatchingCharacterQueue::UpdateStatus( TBool aBufferMode )
{
+ _AKNTRACE_FUNC_ENTER;
TBool isEmergency = EFalse;
TInt err = KErrNone;
TPhCltTelephoneNumber buffer = iCharBuffer;
@@ -308,13 +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;
+ }
//
//
@@ -325,12 +414,15 @@
EXPORT_C CAknEcsDetector::CAknEcsDetector()
{
+ _AKNTRACE_FUNC_ENTER;
iCoeEnv = CCoeEnv::Static();
iState = ENotFullyConstructed;
+ _AKNTRACE_FUNC_EXIT;
}
EXPORT_C CAknEcsDetector::~CAknEcsDetector()
{
+ _AKNTRACE_FUNC_ENTER;
// Must close this in order to remove any observers from the AppUi's monitor
CloseEventSource();
delete iPhCltEmergencyCall;
@@ -338,14 +430,21 @@
delete iQueue;
delete iIdler;
delete iKeyTimeoutTimer;
+ _AKNTRACE_FUNC_EXIT;
}
EXPORT_C void CAknEcsDetector::ConstructL()
{
+ _AKNTRACE_FUNC_ENTER;
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();
@@ -355,14 +454,17 @@
// Timer for timing the timeout between keys
iKeyTimeoutTimer = CPeriodic::NewL( CActive::EPriorityLow);
+ _AKNTRACE_FUNC_EXIT;
}
EXPORT_C CAknEcsDetector* CAknEcsDetector::NewL()
{ // static
+ _AKNTRACE_FUNC_ENTER;
CAknEcsDetector* self = new (ELeave) CAknEcsDetector();
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop(); //self
+ _AKNTRACE_FUNC_EXIT;
return self;
}
@@ -392,30 +494,76 @@
EXPORT_C void CAknEcsDetector::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* /* aDestination */)
{
+ _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;
}
EXPORT_C void CAknEcsDetector::AddChar( TText aNewChar )
{
+ _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.
+ }
+
iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it
- if ( aNewChar == EStdKeyYes || aNewChar ==EKeyPhoneSend )
+ if ( aNewChar == EStdKeyYes || aNewChar == EKeyPhoneSend )
{
- if ( State() == ECompleteMatch )
+ if ( iServiceCallEnabled )
{
- 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
@@ -518,11 +666,13 @@
DetermineState();
iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) );
}
+ _AKNTRACE_FUNC_EXIT;
}
void CAknEcsDetector::DetermineState()
{
+ _AKNTRACE_FUNC_ENTER;
TState bestState = ENoMatch;
if ( iQueue->Count() == 0 )
@@ -541,12 +691,22 @@
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;
}
SetState(bestState);
}
+ _AKNTRACE( "[%s][%s] bestState: %d", "CAknEcsDetector",
+ __FUNCTION__, bestState );
+ _AKNTRACE_FUNC_EXIT;
}
EXPORT_C void CAknEcsDetector::ReportEvent(TState aNewState )
@@ -574,19 +734,41 @@
}
EXPORT_C void CAknEcsDetector::SetBuffer( const TDesC& aNewBuffer )
{
+ _AKNTRACE_FUNC_ENTER;
+ _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknEcsDetector",
+ __FUNCTION__, &aNewBuffer );
+
iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it
iQueue->Reset();
iQueue->SetBuffer(aNewBuffer);
DetermineState();
- if ( State() == ECompleteMatch )
+
+ if ( iServiceCallEnabled )
{
- 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;
}
EXPORT_C void CAknEcsDetector::SetState( TState aNewState )
{
+ _AKNTRACE_FUNC_ENTER;
+ _AKNTRACE( "[%s][%s] aNewState: %d", "CAknEcsDetector",
+ __FUNCTION__, aNewState );
ReportEvent( aNewState );
TInt oldState = iState;
@@ -611,26 +793,45 @@
proceedWithCall = OfferEmergencyCall();
if ( proceedWithCall )
{
+ _AKNTRACE( "[%s][%s] Attempt Emergency Call", "CAknEcsDetector",
+ __FUNCTION__);
AttemptEmergencyCall();
}
else
{ // Pass through this state immediately
+ _AKNTRACE( "[%s][%s] Reset", "CAknEcsDetector", __FUNCTION__);
iQueue->Reset();
SetState( EEmpty );
}
}
break;
+ case EServiceNumMatch:
+ if ( iServiceCallEnabled )
+ {
+ if ( aNewState == ECompleteMatchThenSendKey )
+ {
+ RelinquishCapturedKeys();
+ _AKNTRACE( "[%s][%s] Make Service Call", "CAknEcsDetector",
+ __FUNCTION__);
+ TRAP_IGNORE( MakeServiceCallL() );
+ }
+ }
+ break;
+
default:
break;
}
+ _AKNTRACE_FUNC_EXIT;
}
EXPORT_C void CAknEcsDetector::Reset()
{
+ _AKNTRACE_FUNC_ENTER;
iQueue->Reset();
SetState( EEmpty );
+ _AKNTRACE_FUNC_EXIT;
}
/**
@@ -657,6 +858,7 @@
void CAknEcsDetector::AttemptEmergencyCall()
{
+ _AKNTRACE_FUNC_ENTER;
#ifdef AVKON_RDEBUG_INFO
_LIT(KDebugAttemptEmergencyCall, "Attempt Emergency Call From Detector");
RDebug::Print(KDebugAttemptEmergencyCall);
@@ -668,6 +870,52 @@
{
err = KErrNone;
}
+ _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 )
@@ -690,18 +938,22 @@
*/
TInt CAknEcsDetector::CallAttemptedCallback(TAny* aSelf)
{ // static
+ _AKNTRACE_FUNC_ENTER;
REINTERPRET_CAST(CAknEcsDetector*,aSelf)->SetState( ECallAttempted );
#ifdef AVKON_RDEBUG_INFO
_LIT(KDebugCallAttemptedCallback, "CallAttemptedCallback");
RDebug::Print(KDebugCallAttemptedCallback);
#endif
+ _AKNTRACE_FUNC_EXIT;
return 0;
}
TInt CAknEcsDetector::CancelMatch(TAny* aThis)
{
+ _AKNTRACE_FUNC_ENTER;
static_cast<CAknEcsDetector*>(aThis)->Reset();
static_cast<CAknEcsDetector*>(aThis)->iKeyTimeoutTimer->Cancel();
+ _AKNTRACE_FUNC_EXIT;
return 0; // Do not repeat the operation
}