diff -r 000000000000 -r 3553901f7fa8 telephonyutils/telephonywatchers/src/indicatorwatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyutils/telephonywatchers/src/indicatorwatcher.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +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 + + #include + +// +// ------> 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(WHelpers::Rand(ESACallNone, ESACallAlternating, TheSeed)); + User::LeaveIfError(iCurrentCallProperty.Set(state)); + break; + } + + case 1: // BATTERY CHARGER + { + TSAChargerStatus state = static_cast(WHelpers::Rand(ESAChargerConnected, ESAChargerNotCharging, TheSeed)); + User::LeaveIfError(iChargerStatusProperty.Set(state)); + break; + } + + case 2: // NETWORK AVAILABILITY + { + TSANetworkStatus state = static_cast(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; i0) + 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); + } + + + + + + +