uifw/AvKon/src/AknEcs.cpp
branchRCL_3
changeset 9 aabf2c525e0f
parent 4 8ca85d2f0db7
child 55 aecbbf00d063
--- 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 <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
 
 /** 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;