|
1 /* |
|
2 * Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Support for Emergency Calls. Class Implementations. |
|
15 * Pressed keys are tracked in a buffer and CEmergencyNumberUtils |
|
16 * is used to find out if the buffer matches to emergency number. |
|
17 * Observers, if registered are called to notify them. |
|
18 * |
|
19 * |
|
20 */ |
|
21 |
|
22 |
|
23 |
|
24 // INCLUDES |
|
25 #include <e32std.h> |
|
26 #include "aknenv.h" |
|
27 #include "aknappui.h" |
|
28 #include "AknEcs.h" |
|
29 #include <featmgr.h> |
|
30 #include "AknDebug.h" |
|
31 |
|
32 #include <CPhCltEmergencyCall.h> |
|
33 #include <MPhCltEmergencyCallObserver.h> |
|
34 #include <PhCltTypes.h> |
|
35 #include <AvkonInternalCRKeys.h> |
|
36 #include <PtiDefs.h> |
|
37 #include <e32property.h> |
|
38 #include <AiwCommon.hrh> |
|
39 #include <aiwdialdata.h> |
|
40 #include <AiwServiceHandler.h> |
|
41 #include <centralrepository.h> |
|
42 |
|
43 #include "akntrace.h" |
|
44 |
|
45 const TInt KAknKeyScanCodeBegin = 33; |
|
46 const TInt KAknKeyScanCodeEnd = 126; |
|
47 |
|
48 // CLASS DECLARATIONS |
|
49 |
|
50 /** Class for getting emergency call events */ |
|
51 NONSHARABLE_CLASS(CPhCltEmergencyCallObserver) : public CBase, |
|
52 public MPhCltEmergencyCallObserver |
|
53 { |
|
54 public: |
|
55 /** Constructor */ |
|
56 CPhCltEmergencyCallObserver(CAknEcsDetector* aParent); |
|
57 |
|
58 /** Destructor */ |
|
59 ~CPhCltEmergencyCallObserver( ); |
|
60 |
|
61 /** |
|
62 * This method is called when client's dial request is completed. |
|
63 * |
|
64 * @param aStatus error code of the success of the operation. |
|
65 */ |
|
66 virtual void HandleEmergencyDialL( const TInt aStatus ); |
|
67 private: |
|
68 /** Pointer to the parent object that really handles the events. */ |
|
69 CAknEcsDetector* iParent; |
|
70 }; |
|
71 |
|
72 |
|
73 CPhCltEmergencyCallObserver::CPhCltEmergencyCallObserver(CAknEcsDetector* aParent) |
|
74 :iParent(aParent) |
|
75 { |
|
76 } |
|
77 |
|
78 CPhCltEmergencyCallObserver::~CPhCltEmergencyCallObserver() |
|
79 { |
|
80 } |
|
81 |
|
82 void CPhCltEmergencyCallObserver::HandleEmergencyDialL( const TInt /*aStatus*/ ) |
|
83 { |
|
84 #ifdef AVKON_RDEBUG_INFO |
|
85 _LIT(KDebugDialRequestCompleted, "Dial request is completed"); |
|
86 RDebug::Print(KDebugDialRequestCompleted); |
|
87 #endif |
|
88 iParent->CallAttemptedCallback( iParent ); |
|
89 } |
|
90 |
|
91 /** |
|
92 * Class to hold the queue of keys (TText characters) provided to the emergency call detector. |
|
93 * |
|
94 * Performs matching of an emergency number with the current queue. |
|
95 * |
|
96 * No memory is allocated after its complete construction |
|
97 * |
|
98 */ |
|
99 NONSHARABLE_CLASS(CAknMatchingCharacterQueue) : public CBase |
|
100 { |
|
101 public: |
|
102 /** |
|
103 * These statuses are returned by MatchText |
|
104 */ |
|
105 enum TStatus |
|
106 { |
|
107 ENoMatch, |
|
108 ECompleteMatch, |
|
109 EServiceNumMatch |
|
110 }; |
|
111 public: |
|
112 /** |
|
113 * C++ constructor |
|
114 * |
|
115 * @param aPhCltEmergencyCall Emergency call client |
|
116 * @param aServiceCallEnabled Is service call feature enabled during device or key lock. |
|
117 */ |
|
118 CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled ); |
|
119 |
|
120 /** |
|
121 * C++ destructor |
|
122 */ |
|
123 ~CAknMatchingCharacterQueue( ); |
|
124 |
|
125 /** |
|
126 * 2nd phase constructor |
|
127 */ |
|
128 void ConstructL(); |
|
129 |
|
130 /** |
|
131 * Method to reset the buffer by resetting the pointers. |
|
132 * |
|
133 */ |
|
134 void Reset(); |
|
135 |
|
136 /** |
|
137 * Adds the passed character code to the queue. All codes append to the queue; |
|
138 * none are ignored. |
|
139 * |
|
140 * @param aNewChar New char to the queue. |
|
141 */ |
|
142 void AddChar( TText aNewChar ); |
|
143 |
|
144 |
|
145 /** |
|
146 * Set the entire contents of the queue. If the new buffer is longer than |
|
147 * the queue, rest are stripped. |
|
148 * |
|
149 * @param aNewBuffer New content to the queue. |
|
150 */ |
|
151 void SetBuffer( const TDesC& aNewBuffer ); |
|
152 |
|
153 /** |
|
154 * The number of characters in the queue. Resets to 0. Increases as characters are added |
|
155 * up to and equal to KAknEcsMaxMatchingLength |
|
156 * |
|
157 * @return the number of characters queued and available for match. |
|
158 * |
|
159 */ |
|
160 TInt Count() const; |
|
161 |
|
162 /** |
|
163 * Returns the status of the queue (which is automatically updated when AddChar and other non-const |
|
164 * API is called) |
|
165 * @return The status of the match. Nothing matching returns ENoMatch; |
|
166 * The whole sequence matching returns ECompleteMatch. |
|
167 */ |
|
168 TStatus Status() const; |
|
169 |
|
170 /** |
|
171 * Returns a pointer to the current matching number. |
|
172 * |
|
173 * @return A ptr descriptor into the currently matching text |
|
174 */ |
|
175 TPtrC CurrentMatch() const; |
|
176 |
|
177 /** |
|
178 * Returns an index to the current character buffer where the emergency number |
|
179 * match begins. This value is between 0 and KAknEcsMaxMatchingLength, even if |
|
180 * there have been a large number characters input to the FIFO. Thus, it does not |
|
181 * take account of characters that have fallen out of the FIFO. |
|
182 * |
|
183 * @return the index in the current buffer where the match starts |
|
184 */ |
|
185 TInt IndexOfCurrentMatch() const; |
|
186 |
|
187 /** |
|
188 * Validates the service number. |
|
189 * |
|
190 * @param aNumber Service number to be validated from CenRep. |
|
191 * |
|
192 * @return Returns ETrue if aNumber is a service number, EFalse if not. |
|
193 */ |
|
194 TBool ValidateServiceNumberL( const TDesC& aNumber ); |
|
195 |
|
196 private: |
|
197 /** |
|
198 * Update the status of the queue |
|
199 */ |
|
200 void UpdateStatus( TBool aBufferMode ); |
|
201 |
|
202 private: |
|
203 // Emergency number buffer is as long as maximum sequence |
|
204 TBuf<KAknEcsMaxMatchingLength> iCharBuffer; |
|
205 |
|
206 /** Pointer to phone client interface of emergency call. Not owned */ |
|
207 CPhCltEmergencyCall* iPhCltEmergencyCall; |
|
208 TStatus iStatus; // Holds the status; |
|
209 TInt iMatchPosition; // Position in iCharBuffer from where the match starts. |
|
210 TBool iServiceCallFeature; // True if service call feature is enabled. |
|
211 |
|
212 TAny* iSpare; |
|
213 }; |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 // CLASS IMPLEMENTATIONS |
|
219 |
|
220 /** |
|
221 * Local Panic Function and Panic Codes |
|
222 */ |
|
223 |
|
224 enum TAknEcsPanicCodes |
|
225 { |
|
226 EAknEcsPanicDialLLeft = 1, |
|
227 EAknEcsPanicBadState |
|
228 }; |
|
229 |
|
230 GLDEF_C void Panic(TAknEcsPanicCodes aPanic) |
|
231 { |
|
232 _LIT(KPanicCat,"AknEcs"); |
|
233 User::Panic(KPanicCat, aPanic); |
|
234 } |
|
235 |
|
236 // |
|
237 // Queue used for storing and matching the keys used in emergency number detection |
|
238 // |
|
239 // |
|
240 |
|
241 |
|
242 CAknMatchingCharacterQueue::CAknMatchingCharacterQueue( CPhCltEmergencyCall* aPhCltEmergencyCall, TBool aServiceCallEnabled ) |
|
243 : iPhCltEmergencyCall( aPhCltEmergencyCall ), iServiceCallFeature( aServiceCallEnabled ) |
|
244 { |
|
245 _AKNTRACE_FUNC_ENTER; |
|
246 Reset(); |
|
247 _AKNTRACE_FUNC_EXIT; |
|
248 } |
|
249 |
|
250 CAknMatchingCharacterQueue::~CAknMatchingCharacterQueue( ) |
|
251 { |
|
252 } |
|
253 |
|
254 void CAknMatchingCharacterQueue::ConstructL() |
|
255 { |
|
256 } |
|
257 |
|
258 void CAknMatchingCharacterQueue::Reset() |
|
259 { |
|
260 _AKNTRACE_FUNC_ENTER; |
|
261 iMatchPosition = 0; |
|
262 iCharBuffer.Zero(); |
|
263 _AKNTRACE_FUNC_EXIT; |
|
264 } |
|
265 |
|
266 void CAknMatchingCharacterQueue::AddChar( TText aNewChar ) |
|
267 { |
|
268 _AKNTRACE_FUNC_ENTER; |
|
269 _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknMatchingCharacterQueue", |
|
270 __FUNCTION__,&aNewChar); |
|
271 |
|
272 TInt length = iCharBuffer.Length(); |
|
273 TInt maxLenght = iCharBuffer.MaxLength(); |
|
274 if (length >= maxLenght) |
|
275 { |
|
276 iCharBuffer = iCharBuffer.Right(length - 1); |
|
277 } |
|
278 iCharBuffer.Append( aNewChar ); |
|
279 UpdateStatus( EFalse ); |
|
280 _AKNTRACE_FUNC_EXIT; |
|
281 } |
|
282 |
|
283 void CAknMatchingCharacterQueue::SetBuffer( const TDesC& aNewBuffer ) |
|
284 { |
|
285 _AKNTRACE_FUNC_ENTER; |
|
286 _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknMatchingCharacterQueue", |
|
287 __FUNCTION__,&aNewBuffer); |
|
288 |
|
289 TInt maxLenght = iCharBuffer.MaxLength(); |
|
290 TInt length = aNewBuffer.Length(); |
|
291 if ( length > maxLenght ) |
|
292 { |
|
293 length = maxLenght; |
|
294 } |
|
295 iCharBuffer = aNewBuffer.Left( length ); |
|
296 UpdateStatus( ETrue ); |
|
297 _AKNTRACE_FUNC_EXIT; |
|
298 } |
|
299 |
|
300 TInt CAknMatchingCharacterQueue::Count() const |
|
301 { |
|
302 return iCharBuffer.Length(); |
|
303 } |
|
304 |
|
305 CAknMatchingCharacterQueue::TStatus CAknMatchingCharacterQueue::Status() const |
|
306 { |
|
307 return iStatus; |
|
308 } |
|
309 |
|
310 TPtrC CAknMatchingCharacterQueue::CurrentMatch() const |
|
311 { |
|
312 return TPtrC(iCharBuffer.Right(iCharBuffer.Length() - iMatchPosition)); |
|
313 } |
|
314 |
|
315 TInt CAknMatchingCharacterQueue::IndexOfCurrentMatch() const |
|
316 { |
|
317 return iMatchPosition; |
|
318 } |
|
319 |
|
320 void CAknMatchingCharacterQueue::UpdateStatus( TBool aBufferMode ) |
|
321 { |
|
322 _AKNTRACE_FUNC_ENTER; |
|
323 TBool isEmergency = EFalse; |
|
324 TInt err = KErrNone; |
|
325 TPhCltTelephoneNumber buffer = iCharBuffer; |
|
326 if (iPhCltEmergencyCall) |
|
327 { |
|
328 err = iPhCltEmergencyCall->FindEmergencyPhoneNumber(buffer, isEmergency); |
|
329 } |
|
330 if ( err != KErrNone ) |
|
331 { |
|
332 isEmergency = EFalse; |
|
333 } |
|
334 |
|
335 TInt cbLength = iCharBuffer.Length(); |
|
336 TInt bLength = buffer.Length(); |
|
337 |
|
338 if ( aBufferMode && isEmergency && ( cbLength != bLength ) ) |
|
339 { |
|
340 isEmergency = EFalse; |
|
341 } |
|
342 |
|
343 if ( isEmergency ) |
|
344 { |
|
345 iMatchPosition = cbLength - bLength; |
|
346 iStatus = ECompleteMatch; |
|
347 } |
|
348 else if ( iServiceCallFeature && cbLength >= KAknServiceCallMinLength ) |
|
349 { |
|
350 // Check if this is a service call |
|
351 TBool isServiceNum = EFalse; |
|
352 TRAP_IGNORE( isServiceNum = ValidateServiceNumberL( iCharBuffer ) ); |
|
353 |
|
354 if ( isServiceNum ) |
|
355 { |
|
356 iMatchPosition = 0; |
|
357 iStatus = EServiceNumMatch; |
|
358 } |
|
359 else |
|
360 { |
|
361 iMatchPosition = cbLength; |
|
362 iStatus = ENoMatch; |
|
363 } |
|
364 } |
|
365 else |
|
366 { |
|
367 iMatchPosition = cbLength; |
|
368 iStatus = ENoMatch; |
|
369 } |
|
370 _AKNTRACE( "[%s][%s] iStatus: %d", "CAknMatchingCharacterQueue", |
|
371 __FUNCTION__,iStatus ); |
|
372 _AKNTRACE_FUNC_EXIT; |
|
373 } |
|
374 |
|
375 // ----------------------------------------------------------------------------- |
|
376 // CAknMatchingCharacterQueue::ValidateServiceNumber |
|
377 // |
|
378 // Validates the service phone number. |
|
379 // ----------------------------------------------------------------------------- |
|
380 // |
|
381 TBool CAknMatchingCharacterQueue::ValidateServiceNumberL( const TDesC& aNumber ) |
|
382 { |
|
383 _AKNTRACE_FUNC_ENTER; |
|
384 TBool isServiceNum = EFalse; |
|
385 HBufC* serviceNum = HBufC::NewLC( KAknEcsMaxMatchingLength ); |
|
386 CRepository* cenRep = CRepository::NewLC( KCRUidAvkon ); |
|
387 TPtr bufPtr = serviceNum->Des(); |
|
388 |
|
389 if( cenRep->Get( KAknServiceCallNumber, bufPtr ) != KErrNone ) |
|
390 { |
|
391 CleanupStack::PopAndDestroy( cenRep ); |
|
392 CleanupStack::PopAndDestroy( serviceNum ); |
|
393 return EFalse; |
|
394 } |
|
395 |
|
396 // Check if aNumber matches serviceNum |
|
397 if ( aNumber.Compare( *serviceNum ) == 0 ) |
|
398 { |
|
399 isServiceNum = ETrue; |
|
400 } |
|
401 |
|
402 CleanupStack::PopAndDestroy( cenRep ); |
|
403 CleanupStack::PopAndDestroy( serviceNum ); |
|
404 _AKNTRACE_FUNC_EXIT; |
|
405 return isServiceNum; |
|
406 } |
|
407 |
|
408 // |
|
409 // |
|
410 // Implementation of CAknEcsDetector |
|
411 // (Emergency Call Support Detector) |
|
412 // |
|
413 // |
|
414 |
|
415 EXPORT_C CAknEcsDetector::CAknEcsDetector() |
|
416 { |
|
417 _AKNTRACE_FUNC_ENTER; |
|
418 iCoeEnv = CCoeEnv::Static(); |
|
419 iState = ENotFullyConstructed; |
|
420 _AKNTRACE_FUNC_EXIT; |
|
421 } |
|
422 |
|
423 EXPORT_C CAknEcsDetector::~CAknEcsDetector() |
|
424 { |
|
425 _AKNTRACE_FUNC_ENTER; |
|
426 // Must close this in order to remove any observers from the AppUi's monitor |
|
427 CloseEventSource(); |
|
428 delete iPhCltEmergencyCall; |
|
429 delete iEmergencyCallObserver; |
|
430 delete iQueue; |
|
431 delete iIdler; |
|
432 delete iKeyTimeoutTimer; |
|
433 _AKNTRACE_FUNC_EXIT; |
|
434 } |
|
435 |
|
436 EXPORT_C void CAknEcsDetector::ConstructL() |
|
437 { |
|
438 _AKNTRACE_FUNC_ENTER; |
|
439 iEmergencyCallObserver = new (ELeave) CPhCltEmergencyCallObserver( this ); |
|
440 // Phone client interface |
|
441 iPhCltEmergencyCall = CPhCltEmergencyCall::NewL( iEmergencyCallObserver ); |
|
442 |
|
443 // Check if service call is allowed during device and key lock |
|
444 iServiceCallEnabled = |
|
445 FeatureManager::FeatureSupported( KFeatureIdFfServiceCallWhilePhoneLocked ); |
|
446 |
|
447 iQueue = new (ELeave) CAknMatchingCharacterQueue( iPhCltEmergencyCall, iServiceCallEnabled ); |
|
448 iQueue->ConstructL(); |
|
449 |
|
450 DetermineState(); |
|
451 |
|
452 // Idler for delaying the change of state to Call Attempted |
|
453 iIdler = CIdle::NewL( CActive::EPriorityLow ); |
|
454 |
|
455 // Timer for timing the timeout between keys |
|
456 iKeyTimeoutTimer = CPeriodic::NewL( CActive::EPriorityLow); |
|
457 _AKNTRACE_FUNC_EXIT; |
|
458 } |
|
459 |
|
460 EXPORT_C CAknEcsDetector* CAknEcsDetector::NewL() |
|
461 { // static |
|
462 _AKNTRACE_FUNC_ENTER; |
|
463 CAknEcsDetector* self = new (ELeave) CAknEcsDetector(); |
|
464 CleanupStack::PushL( self ); |
|
465 self->ConstructL(); |
|
466 CleanupStack::Pop(); //self |
|
467 _AKNTRACE_FUNC_EXIT; |
|
468 return self; |
|
469 } |
|
470 |
|
471 EXPORT_C TBool CAknEcsDetector::ConnectToEventSource() |
|
472 { |
|
473 if ( iFlags.IsClear( EEventSourceConnected ) ) |
|
474 { |
|
475 TRAPD( err, iAvkonAppUi->EventMonitor()->AddObserverL(this) ); |
|
476 iFlags.Assign( EEventSourceConnected, ( err == KErrNone ) ); |
|
477 return ( err == KErrNone ); |
|
478 } |
|
479 else |
|
480 { |
|
481 return ETrue; |
|
482 } |
|
483 } |
|
484 |
|
485 EXPORT_C void CAknEcsDetector::CloseEventSource() |
|
486 { |
|
487 if (iFlags.IsSet( EEventSourceConnected ) ) |
|
488 { |
|
489 CAknWsEventMonitor* eventMonitor = iAvkonAppUi->EventMonitor(); |
|
490 eventMonitor->RemoveObserver(this); |
|
491 iFlags.Clear( EEventSourceConnected ); |
|
492 } |
|
493 } |
|
494 |
|
495 EXPORT_C void CAknEcsDetector::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* /* aDestination */) |
|
496 { |
|
497 _AKNTRACE_FUNC_ENTER; |
|
498 _AKNTRACE( "[%s][%s] aEvent.type(): %d, aEvent.Key()->iScanCode :%d", "CAknEcsDetector", |
|
499 __FUNCTION__,aEvent.Type(),aEvent.Key()->iScanCode ); |
|
500 if ( aEvent.Type() == EEventKeyDown || |
|
501 // EKeyPhoneEnd/EKeyNo doesn't send EEVentKeyDown events, so EEventKey is used instead |
|
502 ( ( aEvent.Key()->iScanCode == EStdKeyNo ) && ( aEvent.Type() == EEventKey ) ) ) |
|
503 { |
|
504 AddChar( (TText)(aEvent.Key()->iScanCode ) ); // top 16 ( in Unicode build) bits removed |
|
505 } |
|
506 |
|
507 if ( iServiceCallEnabled ) |
|
508 { |
|
509 // When Cancel is pressed we need to clear the queue |
|
510 if ( iState == EServiceNumMatch && aEvent.Type() == EEventPointer && |
|
511 aEvent.Pointer()->iType == TPointerEvent::EButton1Down ) |
|
512 { |
|
513 // Clear the queue, set state to EEmpty, and cancel any pending timeout |
|
514 Reset(); |
|
515 iKeyTimeoutTimer->Cancel(); |
|
516 } |
|
517 } |
|
518 _AKNTRACE_FUNC_EXIT; |
|
519 } |
|
520 |
|
521 |
|
522 EXPORT_C void CAknEcsDetector::AddChar( TText aNewChar ) |
|
523 { |
|
524 _AKNTRACE_FUNC_ENTER; |
|
525 _AKNTRACE( "[%s][%s] aNewChar: %s", "CAknEcsDetector", |
|
526 __FUNCTION__, &aNewChar ); |
|
527 |
|
528 if (aNewChar == EKeyQwertyOn || aNewChar == EKeyQwertyOff) |
|
529 { |
|
530 _AKNTRACE_FUNC_EXIT; |
|
531 return; // return directly if the aNewChar is slide open/closed. |
|
532 } |
|
533 |
|
534 iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it |
|
535 if ( aNewChar == EStdKeyYes || aNewChar == EKeyPhoneSend ) |
|
536 { |
|
537 if ( iServiceCallEnabled ) |
|
538 { |
|
539 if ( iState == ECompleteMatch || iState == EServiceNumMatch ) |
|
540 { |
|
541 _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", |
|
542 __FUNCTION__ ); |
|
543 SetState( ECompleteMatchThenSendKey ); |
|
544 } |
|
545 } |
|
546 else |
|
547 { |
|
548 if ( iState == ECompleteMatch ) |
|
549 { |
|
550 _AKNTRACE( "[%s][%s] SetState( ECompleteMatchThenSendKey )", "CAknEcsDetector", |
|
551 __FUNCTION__ ); |
|
552 SetState( ECompleteMatchThenSendKey ); |
|
553 } |
|
554 } |
|
555 // else do nothing with it... |
|
556 } |
|
557 else |
|
558 { |
|
559 TText scanCode = aNewChar; |
|
560 |
|
561 if ( scanCode < KAknKeyScanCodeBegin || scanCode > KAknKeyScanCodeEnd ) |
|
562 { |
|
563 // Just return since it is an invalid character |
|
564 return; |
|
565 } |
|
566 |
|
567 #ifdef RD_INTELLIGENT_TEXT_INPUT |
|
568 // Convert scan code to number value here |
|
569 // for 4*10, 3*11, half-qwerty key pad |
|
570 // The convert value is referenced from KeymapBuilder.pl in ptienginev2 |
|
571 // Note: if the product change the scancode defintion,pls change the following |
|
572 // map rules. |
|
573 TInt keyboardLayout = EPtiKeyboardNone; |
|
574 TInt errCode = RProperty::Get( KCRUidAvkon, KAknKeyBoardLayout, keyboardLayout ); |
|
575 if ( errCode == KErrNone && ( keyboardLayout == EPtiKeyboardQwerty4x10 |
|
576 || keyboardLayout == EPtiKeyboardQwerty3x11 ) ) |
|
577 { |
|
578 // using same conventor rule for 3x11 & 4x10 |
|
579 if ( scanCode == EPtiKeyQwertyQ ) |
|
580 { |
|
581 scanCode = EPtiKeyQwerty1; |
|
582 } |
|
583 else if ( scanCode == EPtiKeyQwertyW ) |
|
584 { |
|
585 scanCode = EPtiKeyQwerty2; |
|
586 } |
|
587 else if ( scanCode == EPtiKeyQwertyE ) |
|
588 { |
|
589 scanCode = EPtiKeyQwerty3; |
|
590 } |
|
591 else if ( scanCode == EPtiKeyQwertyR ) |
|
592 { |
|
593 scanCode = EPtiKeyQwerty4; |
|
594 } |
|
595 else if ( scanCode == EPtiKeyQwertyT ) |
|
596 { |
|
597 scanCode = EPtiKeyQwerty5; |
|
598 } |
|
599 else if ( scanCode == EPtiKeyQwertyY ) |
|
600 { |
|
601 scanCode = EPtiKeyQwerty6; |
|
602 } |
|
603 else if ( scanCode == EPtiKeyQwertyU ) |
|
604 { |
|
605 scanCode = EPtiKeyQwerty7; |
|
606 } |
|
607 else if ( scanCode == EPtiKeyQwertyI ) |
|
608 { |
|
609 scanCode = EPtiKeyQwerty8; |
|
610 } |
|
611 else if ( scanCode == EPtiKeyQwertyO ) |
|
612 { |
|
613 scanCode = EPtiKeyQwerty9; |
|
614 } |
|
615 else if ( scanCode == EPtiKeyQwertyP ) |
|
616 { |
|
617 scanCode = EPtiKeyQwerty0; |
|
618 } |
|
619 } |
|
620 else if ( errCode == KErrNone && keyboardLayout == EPtiKeyboardHalfQwerty ) |
|
621 { |
|
622 if ( scanCode == EPtiKeyQwertyE ) |
|
623 { |
|
624 scanCode = EPtiKeyQwerty1; |
|
625 } |
|
626 else if ( scanCode == EPtiKeyQwertyT ) |
|
627 { |
|
628 scanCode = EPtiKeyQwerty2; |
|
629 } |
|
630 else if ( scanCode == EPtiKeyQwertyU ) |
|
631 { |
|
632 scanCode = EPtiKeyQwerty3; |
|
633 } |
|
634 else if ( scanCode == EPtiKeyQwertyD ) |
|
635 { |
|
636 scanCode = EPtiKeyQwerty4; |
|
637 } |
|
638 else if ( scanCode == EPtiKeyQwertyG ) |
|
639 { |
|
640 scanCode = EPtiKeyQwerty5; |
|
641 } |
|
642 else if ( scanCode == EPtiKeyQwertyJ ) |
|
643 { |
|
644 scanCode = EPtiKeyQwerty6; |
|
645 } |
|
646 else if ( scanCode == EPtiKeyQwertyU ) |
|
647 { |
|
648 scanCode = EPtiKeyQwertyC; |
|
649 } |
|
650 else if ( scanCode == EPtiKeyQwertyB ) |
|
651 { |
|
652 scanCode = EPtiKeyQwerty8; |
|
653 } |
|
654 else if ( scanCode == EPtiKeyQwertyM ) |
|
655 { |
|
656 scanCode = EPtiKeyQwerty9; |
|
657 } |
|
658 else if ( scanCode == EPtiKeyQwertySpace ) |
|
659 { |
|
660 scanCode = EPtiKeyQwerty0; |
|
661 } |
|
662 } |
|
663 #endif //RD_INTELLIGENT_TEXT_INPUT |
|
664 |
|
665 iQueue->AddChar( scanCode ); |
|
666 DetermineState(); |
|
667 iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); |
|
668 } |
|
669 _AKNTRACE_FUNC_EXIT; |
|
670 } |
|
671 |
|
672 |
|
673 void CAknEcsDetector::DetermineState() |
|
674 { |
|
675 _AKNTRACE_FUNC_ENTER; |
|
676 TState bestState = ENoMatch; |
|
677 |
|
678 if ( iQueue->Count() == 0 ) |
|
679 { |
|
680 bestState = EEmpty; |
|
681 } |
|
682 else |
|
683 { |
|
684 CAknMatchingCharacterQueue::TStatus matchStatus = iQueue->Status(); |
|
685 |
|
686 switch ( matchStatus ) |
|
687 { |
|
688 case CAknMatchingCharacterQueue::ENoMatch: |
|
689 bestState = ENoMatch; |
|
690 break; |
|
691 case CAknMatchingCharacterQueue::ECompleteMatch: |
|
692 bestState = ECompleteMatch; |
|
693 break; |
|
694 case CAknMatchingCharacterQueue::EServiceNumMatch: |
|
695 if ( iServiceCallEnabled ) |
|
696 { |
|
697 bestState = EServiceNumMatch; |
|
698 break; |
|
699 } |
|
700 // Fall through to default case if service call feature is off |
|
701 default: |
|
702 __ASSERT_DEBUG( 0, Panic(EAknEcsPanicBadState) ); |
|
703 break; |
|
704 } |
|
705 SetState(bestState); |
|
706 } |
|
707 _AKNTRACE( "[%s][%s] bestState: %d", "CAknEcsDetector", |
|
708 __FUNCTION__, bestState ); |
|
709 _AKNTRACE_FUNC_EXIT; |
|
710 } |
|
711 |
|
712 EXPORT_C void CAknEcsDetector::ReportEvent(TState aNewState ) |
|
713 { |
|
714 if (iObserver) |
|
715 { |
|
716 iObserver->HandleEcsEvent( this, aNewState ); |
|
717 } |
|
718 } |
|
719 |
|
720 |
|
721 EXPORT_C TPtrC CAknEcsDetector::CurrentMatch() const |
|
722 { |
|
723 return iQueue->CurrentMatch(); |
|
724 } |
|
725 |
|
726 TInt CAknEcsDetector::IndexOfCurrentMatch() const |
|
727 { |
|
728 return iQueue->IndexOfCurrentMatch(); |
|
729 } |
|
730 |
|
731 EXPORT_C CAknEcsDetector::TState CAknEcsDetector::State() |
|
732 { |
|
733 return iState; |
|
734 } |
|
735 EXPORT_C void CAknEcsDetector::SetBuffer( const TDesC& aNewBuffer ) |
|
736 { |
|
737 _AKNTRACE_FUNC_ENTER; |
|
738 _AKNTRACE( "[%s][%s] aNewBuffer: %s", "CAknEcsDetector", |
|
739 __FUNCTION__, &aNewBuffer ); |
|
740 |
|
741 iKeyTimeoutTimer->Cancel(); // there might be pending timeout; clear it |
|
742 iQueue->Reset(); |
|
743 iQueue->SetBuffer(aNewBuffer); |
|
744 DetermineState(); |
|
745 |
|
746 if ( iServiceCallEnabled ) |
|
747 { |
|
748 if ( iState == ECompleteMatch || iState == EServiceNumMatch ) |
|
749 { |
|
750 iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, |
|
751 KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); |
|
752 } |
|
753 } |
|
754 else |
|
755 { |
|
756 if ( iState == ECompleteMatch ) |
|
757 { |
|
758 _AKNTRACE( "[%s][%s] State() == ECompleteMatch ", "CAknEcsDetector", |
|
759 __FUNCTION__ ); |
|
760 iKeyTimeoutTimer->Start( KEcsInterKeyTimeout, |
|
761 KEcsInterKeyTimeout, TCallBack( CancelMatch, this ) ); |
|
762 } |
|
763 } |
|
764 _AKNTRACE_FUNC_EXIT; |
|
765 } |
|
766 |
|
767 EXPORT_C void CAknEcsDetector::SetState( TState aNewState ) |
|
768 { |
|
769 _AKNTRACE_FUNC_ENTER; |
|
770 _AKNTRACE( "[%s][%s] aNewState: %d", "CAknEcsDetector", |
|
771 __FUNCTION__, aNewState ); |
|
772 ReportEvent( aNewState ); |
|
773 |
|
774 TInt oldState = iState; |
|
775 iState = aNewState; |
|
776 |
|
777 switch ( oldState ) |
|
778 { |
|
779 // All these are OK to go to the next state without transition action: |
|
780 case ENotFullyConstructed: |
|
781 case EEmpty: |
|
782 case ECallAttempted: |
|
783 case ENoMatch: |
|
784 case ECompleteMatchThenSendKey: |
|
785 break; |
|
786 |
|
787 case ECompleteMatch: |
|
788 if ( aNewState == ECompleteMatchThenSendKey ) |
|
789 { |
|
790 RelinquishCapturedKeys(); |
|
791 |
|
792 TBool proceedWithCall = ETrue; |
|
793 proceedWithCall = OfferEmergencyCall(); |
|
794 if ( proceedWithCall ) |
|
795 { |
|
796 _AKNTRACE( "[%s][%s] Attempt Emergency Call", "CAknEcsDetector", |
|
797 __FUNCTION__); |
|
798 AttemptEmergencyCall(); |
|
799 } |
|
800 else |
|
801 { // Pass through this state immediately |
|
802 _AKNTRACE( "[%s][%s] Reset", "CAknEcsDetector", __FUNCTION__); |
|
803 iQueue->Reset(); |
|
804 SetState( EEmpty ); |
|
805 } |
|
806 } |
|
807 break; |
|
808 |
|
809 case EServiceNumMatch: |
|
810 if ( iServiceCallEnabled ) |
|
811 { |
|
812 if ( aNewState == ECompleteMatchThenSendKey ) |
|
813 { |
|
814 RelinquishCapturedKeys(); |
|
815 _AKNTRACE( "[%s][%s] Make Service Call", "CAknEcsDetector", |
|
816 __FUNCTION__); |
|
817 TRAP_IGNORE( MakeServiceCallL() ); |
|
818 } |
|
819 } |
|
820 break; |
|
821 |
|
822 default: |
|
823 break; |
|
824 |
|
825 } |
|
826 _AKNTRACE_FUNC_EXIT; |
|
827 } |
|
828 |
|
829 EXPORT_C void CAknEcsDetector::Reset() |
|
830 { |
|
831 _AKNTRACE_FUNC_ENTER; |
|
832 iQueue->Reset(); |
|
833 SetState( EEmpty ); |
|
834 _AKNTRACE_FUNC_EXIT; |
|
835 } |
|
836 |
|
837 /** |
|
838 * This may be re-implemented to add a confirm query. Re-implementation must not leave |
|
839 * |
|
840 */ |
|
841 EXPORT_C TBool CAknEcsDetector::OfferEmergencyCall() |
|
842 { |
|
843 return ETrue; |
|
844 } |
|
845 |
|
846 void CAknEcsDetector::CaptureKeys() |
|
847 { |
|
848 // Capture Send Key |
|
849 RWindowGroup& groupWin=iCoeEnv->RootWin(); |
|
850 iCapturedKey=groupWin.CaptureKey( EStdKeyYes, 0, 0); |
|
851 } |
|
852 |
|
853 void CAknEcsDetector::RelinquishCapturedKeys() |
|
854 { |
|
855 RWindowGroup& groupWin=iCoeEnv->RootWin(); |
|
856 groupWin.CancelCaptureKey( iCapturedKey ); |
|
857 } |
|
858 |
|
859 void CAknEcsDetector::AttemptEmergencyCall() |
|
860 { |
|
861 _AKNTRACE_FUNC_ENTER; |
|
862 #ifdef AVKON_RDEBUG_INFO |
|
863 _LIT(KDebugAttemptEmergencyCall, "Attempt Emergency Call From Detector"); |
|
864 RDebug::Print(KDebugAttemptEmergencyCall); |
|
865 #endif |
|
866 |
|
867 TRAPD( err, iPhCltEmergencyCall->DialEmergencyCallL( CurrentMatch() ) ); |
|
868 __ASSERT_DEBUG( err==KErrNone, Panic( EAknEcsPanicDialLLeft ) ); |
|
869 if(err != KErrNone) |
|
870 { |
|
871 err = KErrNone; |
|
872 } |
|
873 _AKNTRACE_FUNC_EXIT; |
|
874 } |
|
875 |
|
876 void CAknEcsDetector::MakeServiceCallL() |
|
877 { |
|
878 _AKNTRACE_FUNC_ENTER; |
|
879 if ( iServiceCallEnabled ) |
|
880 { |
|
881 CAiwServiceHandler* aiwServiceHandler = CAiwServiceHandler::NewLC(); |
|
882 RCriteriaArray interest; |
|
883 CleanupClosePushL( interest ); |
|
884 |
|
885 CAiwCriteriaItem* criteria = CAiwCriteriaItem::NewLC( KAiwCmdCall, |
|
886 KAiwCmdCall, _L8( "*" ) ); |
|
887 TUid base; |
|
888 base.iUid = KAiwClassBase; |
|
889 criteria->SetServiceClass( base ); |
|
890 User::LeaveIfError( interest.Append( criteria ) ); |
|
891 aiwServiceHandler->AttachL( interest ); |
|
892 |
|
893 CAiwDialData* dialData = CAiwDialData::NewLC(); |
|
894 dialData->SetCallType( CAiwDialData::EAIWForcedCS ); |
|
895 dialData->SetPhoneNumberL( CurrentMatch() ); |
|
896 dialData->SetWindowGroup( AIWDialData::KAiwGoToIdle ); |
|
897 |
|
898 CAiwGenericParamList& paramList = aiwServiceHandler->InParamListL(); |
|
899 dialData->FillInParamListL( paramList ); |
|
900 |
|
901 TRAPD( err, aiwServiceHandler->ExecuteServiceCmdL( KAiwCmdCall, paramList, |
|
902 aiwServiceHandler->OutParamListL(), 0, NULL ) ); |
|
903 __ASSERT_DEBUG( err == KErrNone, Panic( EAknEcsPanicDialLLeft ) ); |
|
904 |
|
905 //reset the queue |
|
906 iQueue->Reset(); |
|
907 |
|
908 CleanupStack::PopAndDestroy( dialData ); |
|
909 CleanupStack::PopAndDestroy( criteria ); |
|
910 CleanupStack::PopAndDestroy( &interest ); |
|
911 CleanupStack::PopAndDestroy( aiwServiceHandler ); |
|
912 |
|
913 if( err != KErrNone ) |
|
914 { |
|
915 User::Leave( err ); |
|
916 } |
|
917 } |
|
918 _AKNTRACE_FUNC_EXIT; |
|
919 } |
|
920 |
|
921 EXPORT_C void CAknEcsDetector::SetObserver( MAknEcsObserver* aObserver ) |
|
922 { |
|
923 iObserver = aObserver; |
|
924 } |
|
925 |
|
926 /** |
|
927 * It is called whenever status is retrieved (by the client). |
|
928 * |
|
929 * @param aStatus It is the status of the phone. |
|
930 */ |
|
931 void CAknEcsDetector::HandlePhoneStatusL( const TInt /* aStatus */ ) |
|
932 { |
|
933 } |
|
934 |
|
935 /** |
|
936 * This is meant to be called asynchronously in order for the Observer to destroy itself |
|
937 * |
|
938 */ |
|
939 TInt CAknEcsDetector::CallAttemptedCallback(TAny* aSelf) |
|
940 { // static |
|
941 _AKNTRACE_FUNC_ENTER; |
|
942 REINTERPRET_CAST(CAknEcsDetector*,aSelf)->SetState( ECallAttempted ); |
|
943 #ifdef AVKON_RDEBUG_INFO |
|
944 _LIT(KDebugCallAttemptedCallback, "CallAttemptedCallback"); |
|
945 RDebug::Print(KDebugCallAttemptedCallback); |
|
946 #endif |
|
947 _AKNTRACE_FUNC_EXIT; |
|
948 return 0; |
|
949 } |
|
950 |
|
951 TInt CAknEcsDetector::CancelMatch(TAny* aThis) |
|
952 { |
|
953 _AKNTRACE_FUNC_ENTER; |
|
954 static_cast<CAknEcsDetector*>(aThis)->Reset(); |
|
955 static_cast<CAknEcsDetector*>(aThis)->iKeyTimeoutTimer->Cancel(); |
|
956 _AKNTRACE_FUNC_EXIT; |
|
957 return 0; // Do not repeat the operation |
|
958 } |
|
959 |
|
960 // End of File |