--- a/telephonyutils/telephonywatchers/src/indicatorwatcher.cpp Mon May 03 13:37:20 2010 +0300
+++ b/telephonyutils/telephonywatchers/src/indicatorwatcher.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,520 +1,520 @@
-// Copyright (c) 2000-2009 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"
-// which accompanies this distribution, and is available
-// at the URL "http://www.eclipse.org/legal/epl-v10.html".
-//
-// Initial Contributors:
-// Nokia Corporation - initial contribution.
-//
-// Contributors:
-//
-// Description:
-//
-
-// User includes
-#include "watcherlog.h"
-#include "indicatorwatcher.h"
-
-// System includes
-#include <sacls.h>
-
- #include <commsdat.h>
-
-//
-// ------> Global exports
-//
-
-
-//
-// ------> CIndicatorWatcher (source)
-//
-
-CIndicatorWatcher::CIndicatorWatcher()
-: CPhoneWatcher()
- {
- }
-
-CIndicatorWatcher* CIndicatorWatcher::NewL(TAny* /*aWatcherParams*/)
- {
- CIndicatorWatcher* self= new (ELeave) CIndicatorWatcher();
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
- return self;
- }
-
-void CIndicatorWatcher::ConstructL()
- {
- CWatcherBase::ConstructL();
- iCallStateWatcher = new (ELeave) CCallStateWatcher(Phone());
-
- /* Attach to properties for minimum access time */
- User::LeaveIfError(iCurrentCallProperty.Attach(KUidSystemCategory, KUidCurrentCall.iUid));
- User::LeaveIfError(iChargerStatusProperty.Attach(KUidSystemCategory, KUidChargerStatus.iUid));
- User::LeaveIfError(iNetworkStatusProperty.Attach(KUidSystemCategory, KUidNetworkStatus.iUid));
- }
-
-CIndicatorWatcher::~CIndicatorWatcher()
- {
- Cancel();
- delete iCallStateWatcher;
- iCurrentCallProperty.Close();
- iChargerStatusProperty.Close();
- iNetworkStatusProperty.Close();
- }
-
-//
-//
-//
-
-void CIndicatorWatcher::HandlePhoneStateEventL(TInt aCompletionCode)
- {
- switch(IndicatorState())
- {
- case EIndicatorNotYetInitialised:
- case EIndicatorRequestInitialIndicator:
- LOGINDICATOR1("IndicatorWatcher : Requesting initial indicator values");
- Phone().GetIndicator(iStatus, iIndicatorInfo);
- IndicatorState() = EIndicatorWaitingForInitialIndicator;
- SetActive();
- break;
-
- case EIndicatorWaitingForInitialIndicator:
- IndicatorState() = EIndicatorIssuingIndicatorChangeNotification;
- HandleIndicatorUpdateL(aCompletionCode);
- break;
-
- case EIndicatorIssuingIndicatorChangeNotification:
- HandleIndicatorUpdateL(aCompletionCode);
- break;
-
- default:
- __ASSERT_DEBUG(0, IndicatorPanic(EUnexpectedState));
- }
- }
-
-void CIndicatorWatcher::HandleCancel()
- {
- if (Phone().SubSessionHandle() == KNullHandle)
- return;
-
- if (IndicatorState() == EIndicatorWaitingForInitialIndicator)
- Phone().CancelAsyncRequest(EMobilePhoneGetIndicator);
- else if (IndicatorState() == EIndicatorIssuingIndicatorChangeNotification)
- {
- Phone().CancelAsyncRequest(EMobilePhoneNotifyIndicatorChange);
- if (iCallStateWatcher)
- iCallStateWatcher->Cancel();
- }
- }
-
-void CIndicatorWatcher::ReleasePhoneResources()
-//
-// Called by the phone watcher base class. Release any telephony related
-// resources and reset and state.
-//
- {
- // This is only called within RunL and therefore we can't be active
- __ASSERT_DEBUG(!IsActive(), IndicatorPanic(EUnexpectedActiveState));
-
- // Reset state
- iState = EIndicatorNotYetInitialised;
- }
-
-
-//
-//
-//
-
-void CIndicatorWatcher::HandleIndicatorUpdateL(TInt aCompletionCode)
- {
-#ifdef _DEBUG
- LOGINDICATOR2("IndicatorWatcher : Handling phone state change with request result (%d)", aCompletionCode);
-#else
- (void) aCompletionCode;
-#endif
-
-#ifdef WATCHER_TESTING
- // TESTING:
- {
- // Get a random number which controls what state we update...
- TInt index;
- User::LeaveIfError(RProperty::Get(KUidSystemCategory,KUidTestProp_CallStateChange.iUid, index));
- switch(index)
- {
- default:
- case 0: // CALL STATE
- {
- TSACurrentCall state = static_cast<TSACurrentCall>(WHelpers::Rand(ESACallNone, ESACallAlternating, TheSeed));
- User::LeaveIfError(iCurrentCallProperty.Set(state));
- break;
- }
-
- case 1: // BATTERY CHARGER
- {
- TSAChargerStatus state = static_cast<TSAChargerStatus>(WHelpers::Rand(ESAChargerConnected, ESAChargerNotCharging, TheSeed));
- User::LeaveIfError(iChargerStatusProperty.Set(state));
- break;
- }
-
- case 2: // NETWORK AVAILABILITY
- {
- TSANetworkStatus state = static_cast<TSANetworkStatus>(WHelpers::Rand(ESANetworkAvailable, ESANetworkUnAvailable, TheSeed));
- User::LeaveIfError(iNetworkStatusProperty.Set(state));
- break;
- }
- }
-
- SuspendFor(10); // seconds
- return;
- }
-#else
- if (aCompletionCode < KErrNone)
- {
- // Indicate we don't know what the indicator status is
- User::LeaveIfError(iCurrentCallProperty.Set(KErrUnknown));
- User::LeaveIfError(iChargerStatusProperty.Set(KErrUnknown));
- User::LeaveIfError(iNetworkStatusProperty.Set(KErrUnknown));
-
- if (aCompletionCode == KErrNotSupported)
- {
- // If the TSY returns 'Not supported' then it isn't
- // worth re-sending the request, so give up gracefully.
- SetDisabled(_L("IndicatorNotifier : TSY returned not supported (%d)"), aCompletionCode);
- }
- else if (aCompletionCode == KErrCancel)
- {
- // Indicator watcher was cancelled
- SetDisabled(_L("IndicatorNotifier : TSY has cancelled request (%d)"), aCompletionCode);
- }
- else if (aCompletionCode == KWatcherBaseModemNotDetected)
- {
- // We should release all telephony related resources until the
- // phone is available again.
- Cancel();
- Reset();
-
- // The modem / phone cannot be found. Wait until it becomes available again...
- WaitForPhoneToPowerUpL();
- }
- else if (ErrorCountIncrement() >= KErrorRetryCount)
- {
- // We've already tried as many times as possible. Shut ourselves down forever.
- // This watcher will be restarted when the machine is rebooted.
- SetDisabled(_L("IndicatorNotifier : Max retries reached or exceeded. Shutting down until reboot."), 0);
- }
- else
- SuspendFor(KErrorRetryPausePeriod);
- }
- else
- {
- LOGINDICATOR1("IndicatorWatcher : Processing successful indicator event");
-
- // Update charger status if there has been a change
- {
- TInt chargerState;
- User::LeaveIfError(iChargerStatusProperty.Get(chargerState));
-
- TInt newChargerState=KErrUnknown;
-
- if (iIndicatorInfo & RMobilePhone::KIndChargerConnected)
- newChargerState=ESAChargerConnected;
- else
- newChargerState=ESAChargerDisconnected;
-
- if (newChargerState!=chargerState)
- {
- LOGINDICATOR2("IndicatorWatcher : New Charger State %d", newChargerState);
- User::LeaveIfError(iChargerStatusProperty.Set(newChargerState));
- }
- }
-
- // Update network available status if there has been a change
- {
- TInt networkState;
- User::LeaveIfError(iNetworkStatusProperty.Get(networkState));
- TInt newNetworkState=KErrUnknown;
-
- if (iIndicatorInfo & RMobilePhone::KIndNetworkAvailable)
- newNetworkState=ESANetworkAvailable;
- else
- newNetworkState=ESANetworkUnAvailable;
-
- if (newNetworkState!=networkState)
- {
- LOGINDICATOR2("IndicatorWatcher : New Network State %d", newNetworkState);
- User::LeaveIfError(iNetworkStatusProperty.Set(newNetworkState));
- }
- }
-
- // Update call-in-progress status if there has been a change
- {
- TInt callState;
- User::LeaveIfError(iCurrentCallProperty.Get(callState));
- TInt newCallState=KErrUnknown;
-
- if ((iIndicatorInfo & RMobilePhone::KIndCallInProgress) &&
- (callState <= ESACallNone))
- {
- newCallState=iCallStateWatcher->StartCallStateMonitor();
- }
- else if (!(iIndicatorInfo & RMobilePhone::KIndCallInProgress))
- {
- iCallStateWatcher->Cancel();
- newCallState=ESACallNone;
- }
-
- if (newCallState!=callState)
- {
- LOGINDICATOR2("IndicatorWatcher : New Call State %d", newCallState);
- User::LeaveIfError(iCurrentCallProperty.Set(newCallState));
- }
- }
-
- // Issue another request
- Phone().NotifyIndicatorChange(iStatus, iIndicatorInfo);
- SetActive();
- }
-#endif
- }
-
-//
-//
-//
-//
-
-CCallStateWatcher::CCallStateWatcher(RMobilePhone& aPhone, TInt aPriority)
-: CActive(aPriority), iPhone(aPhone)
- {
- CActiveScheduler::Add(this);
- }
-
-CCallStateWatcher::~CCallStateWatcher()
- {
- Cancel();
- }
-
-TInt CCallStateWatcher::StartCallStateMonitor()
- {
- TInt state=KErrUnknown;
- TInt lineCount = 0;
-
- // Find the line and call to open permanently
- TInt error = iPhone.EnumerateLines(lineCount);
- if (error)
- return state;
-
- for(TInt i = 0; i<lineCount; i++)
- {
- RPhone::TLineInfo lineInfo;
- error = iPhone.GetLineInfo(i, lineInfo);
- if (error)
- break; // and return state unknown
-
- error = iLine.Open(iPhone,lineInfo.iName);
- if (error)
- break; // and return state unknown
-
- TInt callCount=0;
- error = iLine.EnumerateCall(callCount);
- if (error)
- {
- iLine.Close();
- break;
- }
-
-// There may be more than one call - but this watcher only supports
-// monitoring first call found
- RLine::TCallInfo callInfo;
- TBool found=EFalse;
- for(TInt i=0;i<callCount;i++)
- {
- error = iLine.GetCallInfo(i,callInfo);
- if((error==KErrNone)&&
- (callInfo.iStatus!=RCall::EStatusIdle)&&
- (callInfo.iStatus!=RCall::EStatusUnknown))
- {
- found=ETrue;
- break;
- }
- }
-
- if(found)
- {
- error = iCall.OpenExistingCall(iLine, callInfo.iCallName);
- if (error)
- {
- // Found the line to monitor but can't open call
- iLine.Close();
- return state;
- }
-
- state = GetCallState();
-
- if (state!=KErrUnknown)
- {
- // Now monitor for further state changes
- iCall.NotifyMobileCallStatusChange(iStatus,iCallState);
- SetActive();
- break;
- }
- else
- {
- iCall.Close();
- iLine.Close();
- return state;
- }
-
- } // end of if (callCount>0)
- else
- {
- // Close this line and look at next one
- iLine.Close();
- }
-
- } // end of for loop
-
- return state;
- }
-
-
-void CCallStateWatcher::RunL()
- {
- if (iStatus.Int() == KErrNone)
- {
- TInt callState;
- User::LeaveIfError(RProperty::Get(KUidSystemCategory, KUidCurrentCall.iUid, callState));
-
- TInt newCallState=KErrUnknown;
-
- newCallState=GetCallState();
-
- if (newCallState!=callState)
- User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidCurrentCall.iUid,newCallState));
-
- if (newCallState != KErrUnknown)
- {
- // Now monitor for further state changes
- iCall.NotifyMobileCallStatusChange(iStatus,iCallState);
- SetActive();
- }
- else
- {
- iCall.Close();
- iLine.Close();
- }
- }
- else
- {
- iCall.Close();
- iLine.Close();
- }
- }
-
-
-void CCallStateWatcher::DoCancel()
- {
- iCall.CancelAsyncRequest(EMobileCallNotifyMobileCallStatusChange);
- iCall.Close();
- iLine.Close();
- }
-
-TInt CCallStateWatcher::RunError(TInt /*aError*/)
- {
- // Release resources
- iCall.Close();
- iLine.Close();
- return KErrNone;
- }
-
-TInt CCallStateWatcher::GetCallState()
- {
- TInt state=KErrUnknown;
-
- RMobileCall::TMobileCallInfoV1 info;
- RMobileCall::TMobileCallInfoV1Pckg infoPckg(info);
-
- TInt error = iCall.GetMobileCallInfo(infoPckg);
- if (error)
- {
- // Found the call to monitor but can't get information
- return state;
- }
-
- switch (info.iStatus)
- {
- case RMobileCall::EStatusRinging:
- state = ESACallRinging;
- break;
- case RMobileCall::EStatusDialling:
- state = ESACallDialling;
- break;
- case RMobileCall::EStatusConnecting:
- state = ESACallAlerting;
- break;
- case RMobileCall::EStatusAnswering:
- state = ESACallAnswering;
- break;
- case RMobileCall::EStatusDisconnecting:
- case RMobileCall::EStatusDisconnectingWithInband:
- state = ESACallDisconnecting;
- break;
- case RMobileCall::EStatusConnected:
- case RMobileCall::EStatusHold:
- case RMobileCall::EStatusReconnectPending:
- {
- // Call is connected, so update with type of connected call
- if((info.iValid & RMobileCall::KCallAlternating)&&
- (info.iAlternatingCall != RMobilePhone::EAlternatingModeSingle))
- state = ESACallAlternating;
- else
- {
- switch (info.iService)
- {
- case RMobilePhone::EVoiceService:
- case RMobilePhone::EAuxVoiceService:
- state = ESACallVoice;
- break;
- case RMobilePhone::ECircuitDataService:
- state = ESACallData;
- break;
- case RMobilePhone::EFaxService:
- state = ESACallFax;
- break;
- default:
- // Not a valid call service
- break;
- }
- }
- }
- break;
- default:
- // must be idle state - or special idle state
- state = ESACallNone;
- break;
- }
-
- return state;
- }
-
-//
-//
-//
-
-//
-// Panic Function
-//
-void CIndicatorWatcher::IndicatorPanic(TWatcherPanic aPanicNumber)
- {
- _LIT(panicText,"Indicator Watcher");
- User::Panic(panicText,aPanicNumber);
- }
-
-
-
-
-
-
-
+// Copyright (c) 2000-2009 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"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+// User includes
+#include "watcherlog.h"
+#include "indicatorwatcher.h"
+
+// System includes
+#include <sacls.h>
+
+ #include <commsdat.h>
+
+//
+// ------> Global exports
+//
+
+
+//
+// ------> CIndicatorWatcher (source)
+//
+
+CIndicatorWatcher::CIndicatorWatcher()
+: CPhoneWatcher()
+ {
+ }
+
+CIndicatorWatcher* CIndicatorWatcher::NewL(TAny* /*aWatcherParams*/)
+ {
+ CIndicatorWatcher* self= new (ELeave) CIndicatorWatcher();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+void CIndicatorWatcher::ConstructL()
+ {
+ CWatcherBase::ConstructL();
+ iCallStateWatcher = new (ELeave) CCallStateWatcher(Phone());
+
+ /* Attach to properties for minimum access time */
+ User::LeaveIfError(iCurrentCallProperty.Attach(KUidSystemCategory, KUidCurrentCall.iUid));
+ User::LeaveIfError(iChargerStatusProperty.Attach(KUidSystemCategory, KUidChargerStatus.iUid));
+ User::LeaveIfError(iNetworkStatusProperty.Attach(KUidSystemCategory, KUidNetworkStatus.iUid));
+ }
+
+CIndicatorWatcher::~CIndicatorWatcher()
+ {
+ Cancel();
+ delete iCallStateWatcher;
+ iCurrentCallProperty.Close();
+ iChargerStatusProperty.Close();
+ iNetworkStatusProperty.Close();
+ }
+
+//
+//
+//
+
+void CIndicatorWatcher::HandlePhoneStateEventL(TInt aCompletionCode)
+ {
+ switch(IndicatorState())
+ {
+ case EIndicatorNotYetInitialised:
+ case EIndicatorRequestInitialIndicator:
+ LOGINDICATOR1("IndicatorWatcher : Requesting initial indicator values");
+ Phone().GetIndicator(iStatus, iIndicatorInfo);
+ IndicatorState() = EIndicatorWaitingForInitialIndicator;
+ SetActive();
+ break;
+
+ case EIndicatorWaitingForInitialIndicator:
+ IndicatorState() = EIndicatorIssuingIndicatorChangeNotification;
+ HandleIndicatorUpdateL(aCompletionCode);
+ break;
+
+ case EIndicatorIssuingIndicatorChangeNotification:
+ HandleIndicatorUpdateL(aCompletionCode);
+ break;
+
+ default:
+ __ASSERT_DEBUG(0, IndicatorPanic(EUnexpectedState));
+ }
+ }
+
+void CIndicatorWatcher::HandleCancel()
+ {
+ if (Phone().SubSessionHandle() == KNullHandle)
+ return;
+
+ if (IndicatorState() == EIndicatorWaitingForInitialIndicator)
+ Phone().CancelAsyncRequest(EMobilePhoneGetIndicator);
+ else if (IndicatorState() == EIndicatorIssuingIndicatorChangeNotification)
+ {
+ Phone().CancelAsyncRequest(EMobilePhoneNotifyIndicatorChange);
+ if (iCallStateWatcher)
+ iCallStateWatcher->Cancel();
+ }
+ }
+
+void CIndicatorWatcher::ReleasePhoneResources()
+//
+// Called by the phone watcher base class. Release any telephony related
+// resources and reset and state.
+//
+ {
+ // This is only called within RunL and therefore we can't be active
+ __ASSERT_DEBUG(!IsActive(), IndicatorPanic(EUnexpectedActiveState));
+
+ // Reset state
+ iState = EIndicatorNotYetInitialised;
+ }
+
+
+//
+//
+//
+
+void CIndicatorWatcher::HandleIndicatorUpdateL(TInt aCompletionCode)
+ {
+#ifdef _DEBUG
+ LOGINDICATOR2("IndicatorWatcher : Handling phone state change with request result (%d)", aCompletionCode);
+#else
+ (void) aCompletionCode;
+#endif
+
+#ifdef WATCHER_TESTING
+ // TESTING:
+ {
+ // Get a random number which controls what state we update...
+ TInt index;
+ User::LeaveIfError(RProperty::Get(KUidSystemCategory,KUidTestProp_CallStateChange.iUid, index));
+ switch(index)
+ {
+ default:
+ case 0: // CALL STATE
+ {
+ TSACurrentCall state = static_cast<TSACurrentCall>(WHelpers::Rand(ESACallNone, ESACallAlternating, TheSeed));
+ User::LeaveIfError(iCurrentCallProperty.Set(state));
+ break;
+ }
+
+ case 1: // BATTERY CHARGER
+ {
+ TSAChargerStatus state = static_cast<TSAChargerStatus>(WHelpers::Rand(ESAChargerConnected, ESAChargerNotCharging, TheSeed));
+ User::LeaveIfError(iChargerStatusProperty.Set(state));
+ break;
+ }
+
+ case 2: // NETWORK AVAILABILITY
+ {
+ TSANetworkStatus state = static_cast<TSANetworkStatus>(WHelpers::Rand(ESANetworkAvailable, ESANetworkUnAvailable, TheSeed));
+ User::LeaveIfError(iNetworkStatusProperty.Set(state));
+ break;
+ }
+ }
+
+ SuspendFor(10); // seconds
+ return;
+ }
+#else
+ if (aCompletionCode < KErrNone)
+ {
+ // Indicate we don't know what the indicator status is
+ User::LeaveIfError(iCurrentCallProperty.Set(KErrUnknown));
+ User::LeaveIfError(iChargerStatusProperty.Set(KErrUnknown));
+ User::LeaveIfError(iNetworkStatusProperty.Set(KErrUnknown));
+
+ if (aCompletionCode == KErrNotSupported)
+ {
+ // If the TSY returns 'Not supported' then it isn't
+ // worth re-sending the request, so give up gracefully.
+ SetDisabled(_L("IndicatorNotifier : TSY returned not supported (%d)"), aCompletionCode);
+ }
+ else if (aCompletionCode == KErrCancel)
+ {
+ // Indicator watcher was cancelled
+ SetDisabled(_L("IndicatorNotifier : TSY has cancelled request (%d)"), aCompletionCode);
+ }
+ else if (aCompletionCode == KWatcherBaseModemNotDetected)
+ {
+ // We should release all telephony related resources until the
+ // phone is available again.
+ Cancel();
+ Reset();
+
+ // The modem / phone cannot be found. Wait until it becomes available again...
+ WaitForPhoneToPowerUpL();
+ }
+ else if (ErrorCountIncrement() >= KErrorRetryCount)
+ {
+ // We've already tried as many times as possible. Shut ourselves down forever.
+ // This watcher will be restarted when the machine is rebooted.
+ SetDisabled(_L("IndicatorNotifier : Max retries reached or exceeded. Shutting down until reboot."), 0);
+ }
+ else
+ SuspendFor(KErrorRetryPausePeriod);
+ }
+ else
+ {
+ LOGINDICATOR1("IndicatorWatcher : Processing successful indicator event");
+
+ // Update charger status if there has been a change
+ {
+ TInt chargerState;
+ User::LeaveIfError(iChargerStatusProperty.Get(chargerState));
+
+ TInt newChargerState=KErrUnknown;
+
+ if (iIndicatorInfo & RMobilePhone::KIndChargerConnected)
+ newChargerState=ESAChargerConnected;
+ else
+ newChargerState=ESAChargerDisconnected;
+
+ if (newChargerState!=chargerState)
+ {
+ LOGINDICATOR2("IndicatorWatcher : New Charger State %d", newChargerState);
+ User::LeaveIfError(iChargerStatusProperty.Set(newChargerState));
+ }
+ }
+
+ // Update network available status if there has been a change
+ {
+ TInt networkState;
+ User::LeaveIfError(iNetworkStatusProperty.Get(networkState));
+ TInt newNetworkState=KErrUnknown;
+
+ if (iIndicatorInfo & RMobilePhone::KIndNetworkAvailable)
+ newNetworkState=ESANetworkAvailable;
+ else
+ newNetworkState=ESANetworkUnAvailable;
+
+ if (newNetworkState!=networkState)
+ {
+ LOGINDICATOR2("IndicatorWatcher : New Network State %d", newNetworkState);
+ User::LeaveIfError(iNetworkStatusProperty.Set(newNetworkState));
+ }
+ }
+
+ // Update call-in-progress status if there has been a change
+ {
+ TInt callState;
+ User::LeaveIfError(iCurrentCallProperty.Get(callState));
+ TInt newCallState=KErrUnknown;
+
+ if ((iIndicatorInfo & RMobilePhone::KIndCallInProgress) &&
+ (callState <= ESACallNone))
+ {
+ newCallState=iCallStateWatcher->StartCallStateMonitor();
+ }
+ else if (!(iIndicatorInfo & RMobilePhone::KIndCallInProgress))
+ {
+ iCallStateWatcher->Cancel();
+ newCallState=ESACallNone;
+ }
+
+ if (newCallState!=callState)
+ {
+ LOGINDICATOR2("IndicatorWatcher : New Call State %d", newCallState);
+ User::LeaveIfError(iCurrentCallProperty.Set(newCallState));
+ }
+ }
+
+ // Issue another request
+ Phone().NotifyIndicatorChange(iStatus, iIndicatorInfo);
+ SetActive();
+ }
+#endif
+ }
+
+//
+//
+//
+//
+
+CCallStateWatcher::CCallStateWatcher(RMobilePhone& aPhone, TInt aPriority)
+: CActive(aPriority), iPhone(aPhone)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CCallStateWatcher::~CCallStateWatcher()
+ {
+ Cancel();
+ }
+
+TInt CCallStateWatcher::StartCallStateMonitor()
+ {
+ TInt state=KErrUnknown;
+ TInt lineCount = 0;
+
+ // Find the line and call to open permanently
+ TInt error = iPhone.EnumerateLines(lineCount);
+ if (error)
+ return state;
+
+ for(TInt i = 0; i<lineCount; i++)
+ {
+ RPhone::TLineInfo lineInfo;
+ error = iPhone.GetLineInfo(i, lineInfo);
+ if (error)
+ break; // and return state unknown
+
+ error = iLine.Open(iPhone,lineInfo.iName);
+ if (error)
+ break; // and return state unknown
+
+ TInt callCount=0;
+ error = iLine.EnumerateCall(callCount);
+ if (error)
+ {
+ iLine.Close();
+ break;
+ }
+
+// There may be more than one call - but this watcher only supports
+// monitoring first call found
+ RLine::TCallInfo callInfo;
+ TBool found=EFalse;
+ for(TInt i=0;i<callCount;i++)
+ {
+ error = iLine.GetCallInfo(i,callInfo);
+ if((error==KErrNone)&&
+ (callInfo.iStatus!=RCall::EStatusIdle)&&
+ (callInfo.iStatus!=RCall::EStatusUnknown))
+ {
+ found=ETrue;
+ break;
+ }
+ }
+
+ if(found)
+ {
+ error = iCall.OpenExistingCall(iLine, callInfo.iCallName);
+ if (error)
+ {
+ // Found the line to monitor but can't open call
+ iLine.Close();
+ return state;
+ }
+
+ state = GetCallState();
+
+ if (state!=KErrUnknown)
+ {
+ // Now monitor for further state changes
+ iCall.NotifyMobileCallStatusChange(iStatus,iCallState);
+ SetActive();
+ break;
+ }
+ else
+ {
+ iCall.Close();
+ iLine.Close();
+ return state;
+ }
+
+ } // end of if (callCount>0)
+ else
+ {
+ // Close this line and look at next one
+ iLine.Close();
+ }
+
+ } // end of for loop
+
+ return state;
+ }
+
+
+void CCallStateWatcher::RunL()
+ {
+ if (iStatus.Int() == KErrNone)
+ {
+ TInt callState;
+ User::LeaveIfError(RProperty::Get(KUidSystemCategory, KUidCurrentCall.iUid, callState));
+
+ TInt newCallState=KErrUnknown;
+
+ newCallState=GetCallState();
+
+ if (newCallState!=callState)
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory,KUidCurrentCall.iUid,newCallState));
+
+ if (newCallState != KErrUnknown)
+ {
+ // Now monitor for further state changes
+ iCall.NotifyMobileCallStatusChange(iStatus,iCallState);
+ SetActive();
+ }
+ else
+ {
+ iCall.Close();
+ iLine.Close();
+ }
+ }
+ else
+ {
+ iCall.Close();
+ iLine.Close();
+ }
+ }
+
+
+void CCallStateWatcher::DoCancel()
+ {
+ iCall.CancelAsyncRequest(EMobileCallNotifyMobileCallStatusChange);
+ iCall.Close();
+ iLine.Close();
+ }
+
+TInt CCallStateWatcher::RunError(TInt /*aError*/)
+ {
+ // Release resources
+ iCall.Close();
+ iLine.Close();
+ return KErrNone;
+ }
+
+TInt CCallStateWatcher::GetCallState()
+ {
+ TInt state=KErrUnknown;
+
+ RMobileCall::TMobileCallInfoV1 info;
+ RMobileCall::TMobileCallInfoV1Pckg infoPckg(info);
+
+ TInt error = iCall.GetMobileCallInfo(infoPckg);
+ if (error)
+ {
+ // Found the call to monitor but can't get information
+ return state;
+ }
+
+ switch (info.iStatus)
+ {
+ case RMobileCall::EStatusRinging:
+ state = ESACallRinging;
+ break;
+ case RMobileCall::EStatusDialling:
+ state = ESACallDialling;
+ break;
+ case RMobileCall::EStatusConnecting:
+ state = ESACallAlerting;
+ break;
+ case RMobileCall::EStatusAnswering:
+ state = ESACallAnswering;
+ break;
+ case RMobileCall::EStatusDisconnecting:
+ case RMobileCall::EStatusDisconnectingWithInband:
+ state = ESACallDisconnecting;
+ break;
+ case RMobileCall::EStatusConnected:
+ case RMobileCall::EStatusHold:
+ case RMobileCall::EStatusReconnectPending:
+ {
+ // Call is connected, so update with type of connected call
+ if((info.iValid & RMobileCall::KCallAlternating)&&
+ (info.iAlternatingCall != RMobilePhone::EAlternatingModeSingle))
+ state = ESACallAlternating;
+ else
+ {
+ switch (info.iService)
+ {
+ case RMobilePhone::EVoiceService:
+ case RMobilePhone::EAuxVoiceService:
+ state = ESACallVoice;
+ break;
+ case RMobilePhone::ECircuitDataService:
+ state = ESACallData;
+ break;
+ case RMobilePhone::EFaxService:
+ state = ESACallFax;
+ break;
+ default:
+ // Not a valid call service
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ // must be idle state - or special idle state
+ state = ESACallNone;
+ break;
+ }
+
+ return state;
+ }
+
+//
+//
+//
+
+//
+// Panic Function
+//
+void CIndicatorWatcher::IndicatorPanic(TWatcherPanic aPanicNumber)
+ {
+ _LIT(panicText,"Indicator Watcher");
+ User::Panic(panicText,aPanicNumber);
+ }
+
+
+
+
+
+
+