uifw/AvKon/src/AknEcs.cpp
branchRCL_3
changeset 56 d48ab3b357f1
parent 55 aecbbf00d063
--- 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
     }