--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/telephonyutils/telephonywatchers/src/watcherbase.cpp Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,594 @@
+// 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:
+//
+
+#include "watcherbase.h"
+#include "watcherlog.h"
+
+// System includes
+ #include <commsdattypesv1_1.h>
+ #include <commsdat_partner.h>
+
+ #include <sacls.h>
+
+ using namespace CommsDat;
+
+// User includes
+#include "phoneonoff.h"
+
+// Constants
+const TInt KOneSecond = 1000000;
+
+
+
+//
+// ------> Global exports
+//
+
+
+//
+// ------> CWatcherBase (source)
+//
+
+EXPORT_C CWatcherBase::CWatcherBase(TInt aPriority)
+: CActive(aPriority)
+ {
+ CActiveScheduler::Add(this);
+
+#ifdef WATCHER_TESTING
+ //-- this section of code is used by TE_TelWatchers(Unit) test
+ TTime now;
+ now.UniversalTime();
+ TheSeed = now.Int64();
+
+ //-- define properties for test purposes
+ LOGCOMMON1("CTelWatcherBase : defining properties for testing");
+
+ //-- For debugging purposes only, used by TE_TelWatchers(Unit).
+
+ //- this property change (to any value) informs that CTelPhoneWatcher has re-read modem table from commdb in
+ //- CTelPhoneWatcher::DoRetrieveTSYNameL().
+ RProperty::Define(KUidSystemCategory, KUidTestProp_ModemTableRefreshed.iUid, RProperty::EInt);
+
+ //- this property changes in CTelPhoneWatcher::HandleModemChangedL()
+ //- when the commsdb modem record has changed
+ RProperty::Define(KUidSystemCategory, KUidTestProp_ModemRecordChanged.iUid, RProperty::EInt);
+
+ //-- this property is used in CIndicatorWatcher::HandleIndicatorUpdateL()
+ //-- to simulate call state change by t_watchers test
+ RProperty::Define(KUidSystemCategory, KUidTestProp_CallStateChange.iUid, RProperty::EInt);
+
+ //-- this property is used to disable and reset phone watchers
+ RProperty::Define(KUidSystemCategory, KUidTestProp_WatchersDisable.iUid, RProperty::EInt);
+#endif
+ }
+
+EXPORT_C CWatcherBase::~CWatcherBase()
+ {
+ Cancel();
+ iTimer.Close();
+ iPhonePowerProperty.Close();
+ }
+
+EXPORT_C void CWatcherBase::ConstructL()
+ {
+ LOGCOMMON1("WatcherBase : Creating timer");
+ User::LeaveIfError(iTimer.CreateLocal());
+
+ User::LeaveIfError(iPhonePowerProperty.Attach(KUidSystemCategory, KUidPhonePwr.iUid));
+
+ // This starts the whole ball rolling
+ RequestNextState();
+ }
+
+//
+//
+//
+
+EXPORT_C void CWatcherBase::SuspendFor(TInt aTimeInSeconds)
+ {
+ LOGCOMMON1("WatcherBase : Pausing after error");
+ TTimeIntervalMicroSeconds32 timeToSuspendFor = aTimeInSeconds * KOneSecond;
+ iTimer.After(iStatus, timeToSuspendFor);
+ State() = EBaseStateSuspending;
+ SetActive();
+ }
+
+EXPORT_C void CWatcherBase::SetDisabled(const TDesC& aLogEntry, TInt aError)
+ {
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tmpBuf;
+ tmpBuf.Copy(aLogEntry);
+ LOGCOMMON3("Log Entry \"%S\" error %d", &tmpBuf, aError);
+#else
+ (void) aLogEntry;
+ (void) aError;
+#endif
+ LOGCOMMON1("WatcherBase : Watcher is now disabled");
+ State() = EBaseStateDisabled;
+ }
+
+EXPORT_C void CWatcherBase::RequestNextState()
+ {
+ LOGCOMMON1("WatcherBase : Requesting State Change");
+
+ if (State() != EBaseStateDisabled)
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+ }
+
+EXPORT_C void CWatcherBase::WaitForPhoneToPowerUpL()
+//
+// The phone is currently turned off. We must wait for it to be turned back on
+// again before the watchers can continue.
+//
+ {
+ TInt val;
+
+ LOGCOMMON1("WatcherBase : Waiting for phone to be turned on");
+ __ASSERT_DEBUG(!IsActive(), WatcherBasePanic(EUnexpectedActiveState));
+ Cancel();
+
+ //-- Subscribe to phone power state change property and wait until it changes
+ iPhonePowerProperty.Subscribe(iStatus);
+
+ // Update our state
+ State() = EBaseStateWaitingForPhoneToPowerUp;
+
+ // Set us ready to go again
+ SetActive();
+
+ User::LeaveIfError(iPhonePowerProperty.Get(val));
+
+ if (val != ESAPhoneOff)
+ {//-- phone is already ON, complete request so that we go to RunL without waiting
+ iPhonePowerProperty.Cancel();
+ LOGCOMMON1("CTelWatcherBase::WaitForPhoneToPowerUpL ??? phone is already turned ON");
+ }
+ }
+
+//
+//
+//
+
+EXPORT_C void CWatcherBase::RunL()
+ {
+ LOGCOMMON2("WatcherBase : RunL(%d)", iStatus.Int());
+
+ switch(State())
+ {
+ case EBaseStateConnectingToPropertyNotifier:
+ LOGCOMMON1("WatcherBase : Attaching to Property");
+
+ // Virtual function call back, for any subclasses that need to implement
+ // any special stuff.
+ HandleConnectionToChangeNotifierEstablishedL();
+
+ // Move to next state
+ State() = EBaseStatePassive;
+ RequestNextState();
+ break;
+
+ case EBaseStateWaitingForPhoneToPowerUp:
+ // We were waiting for the phone to become available again. We now must restart
+ // this watcher from scratch.
+ LOGCOMMON1("WatcherBase : Phone available again. Restarting watcher framework");
+
+ //-- phone power state has changed (it must be turned ON)
+ //-- retrieve its state and check.
+ TInt val;
+
+ User::LeaveIfError(iPhonePowerProperty.Get(val));
+
+ if (val == ESAPhoneOn)
+ { //-- everything OK, the phone has been turned ON, restart this watcher from scratch.
+ LOGCOMMON1("CTelWatcherBase : Phone has been turned ON. Restarting watcher framework");
+ State() = EBaseStateConnectingToPropertyNotifier;
+ RequestNextState();
+ }
+ else
+ { //-- strange situation, we were waiting for phone On and it now Off, try to wait again
+ LOGCOMMON1("CTelWatcherBase : ??? Phone has been turned OFF. Continue waiting...");
+ WaitForPhoneToPowerUpL();
+ }
+ break;
+
+ case EBaseStateSuspending:
+ LOGCOMMON1("WatcherBase : Completed suspension. Resuming passive state");
+
+ State() = EBaseStatePassive; // Fall through
+
+ case EBaseStatePassive: // In passive mode, so just call framework function
+ HandleStateEventL(iStatus.Int());
+ break;
+
+ default:
+ case EBaseStateDisabled:
+ LOGCOMMON1("WatcherBase : RunL called in Disabled state. Ooops");
+ __ASSERT_DEBUG(0, WatcherBasePanic(EUnexpectedState));
+ }
+ }
+
+EXPORT_C void CWatcherBase::DoCancel()
+ {
+ switch(State())
+ {
+ case EBaseStateSuspending:
+ // Cancel outstanding timer
+ iTimer.Cancel();
+ break;
+
+ case EBaseStateWaitingForPhoneToPowerUp:
+ // Cancel outstanding asynchronous request
+ iPhonePowerProperty.Cancel();
+ break;
+
+ default:
+ case EBaseStatePassive:
+ case EBaseStateConnectingToPropertyNotifier:
+ case EBaseStateDisabled:
+ break;
+ }
+
+ // Let other sub classes cancel their requests
+ HandleCancel();
+ }
+
+EXPORT_C TInt CWatcherBase::RunError(TInt aError)
+//
+// Called when RunL (or a sub-function there-of) leaves.
+//
+ {
+#ifdef _WATCHER_LOGGING_ENABLED
+ LOGCOMMON2("WatcherBase : RunError called with error of %d", aError);
+#else
+ (void) aError;
+#endif
+
+ // Should never be called from outside the framework
+ __ASSERT_DEBUG(!IsActive(), WatcherBasePanic(EUnexpectedActiveState));
+ Cancel();
+
+ // Reset all resources in this, and the derrived class so that
+ // we can start up again (from scratch) (virtual function).
+ if (State() == EBaseStatePassive)
+ Reset();
+
+ // Close our resources
+ iPhonePowerProperty.Close();
+
+ // NOTE: we don't close the timer. This was opened in ConstructL so
+ // we can't close that here.
+
+ // Have we already tried this too many times?
+ if (ErrorCountIncrement() >= KErrorRetryCount)
+ {
+ // We've tried to resume 3 times already and we've still not managed. Give up
+ // now until a reboot.
+ SetDisabled(_L("WatcherBase : RunError called too many times in succession"), KErrNone);
+ }
+ else
+ {
+ // Put us in the start up state again
+ LOGCOMMON1("WatcherBase : Phone available again. Restarting watcher framework");
+ State() = EBaseStateConnectingToPropertyNotifier;
+ RequestNextState();
+ }
+
+ return KErrNone;
+ }
+
+//
+// Panic Function
+//
+void CWatcherBase::WatcherBasePanic(TWatcherPanic aPanicNumber)
+ {
+ _LIT(panicText,"Watcher Base");
+ User::Panic(panicText,aPanicNumber);
+ }
+
+
+
+//
+// ------> CPhoneWatcher (source)
+//
+
+
+EXPORT_C CPhoneWatcher::CPhoneWatcher(TInt aPriority)
+: CWatcherBase(aPriority)
+ {
+ }
+
+EXPORT_C CPhoneWatcher::~CPhoneWatcher()
+ {
+ delete iModemChangeObserver;
+ delete iPhoneWait;
+ Phone().Close();
+ ETel().Close();
+ }
+
+EXPORT_C void CPhoneWatcher::ConstructL()
+ {
+ CWatcherBase::ConstructL();
+ }
+
+//
+//
+//
+
+EXPORT_C void CPhoneWatcher::HandleStateEventL(TInt aCompletionCode)
+ {
+ switch(PhoneState())
+ {
+ case EPhoneStateRetrievingTsyName:
+ // Cconstruct observers
+ if (!iPhoneWait)
+ {
+ iPhoneWait = new(ELeave) CPhoneOnOff(*this);
+ iPhoneWait->ConstructL();
+ }
+ if (!iModemChangeObserver)
+ {
+ iModemChangeObserver = new(ELeave) CModemChangeObserver(*this);
+ iModemChangeObserver->ConstructL();
+ }
+
+ User::LeaveIfError(RetrieveTSYName());
+ PhoneState() = EPhoneStateConnectingToETel;
+ RequestNextState();
+ break;
+
+ case EPhoneStateConnectingToETel:
+ User::LeaveIfError(ConnectToETelServer());
+ PhoneState() = EPhoneStateLoadingPhoneModule;
+ RequestNextState();
+ break;
+
+ case EPhoneStateLoadingPhoneModule:
+ User::LeaveIfError(LoadPhoneModule());
+ PhoneState() = EPhoneStateConnectingToPhone;
+ RequestNextState();
+ break;
+
+ case EPhoneStateConnectingToPhone:
+ User::LeaveIfError(ConnectToPhone());
+ PhoneState() = EPhoneStatePassive;
+ RequestNextState();
+ break;
+
+ case EPhoneStatePassive:
+ HandlePhoneStateEventL(aCompletionCode);
+ break;
+
+ default:
+ __ASSERT_DEBUG(0, WatcherBasePanic(EUnexpectedState));
+ }
+ }
+
+EXPORT_C void CPhoneWatcher::Reset()
+ {
+ // Ensures CModemChangeObserver object stops running
+ if (iModemChangeObserver)
+ {
+ iModemChangeObserver->Cancel();
+ }
+
+ if (PhoneState() == EPhoneStatePassive)
+ {
+ // Get children to release any resources they have
+ ReleasePhoneResources();
+ }
+
+ // Close our connections to the phone & ETel
+ Phone().Close();
+ ETel().Close();
+
+ // Reset state
+ PhoneState() = EPhoneStateRetrievingTsyName;
+ }
+
+//
+//
+//
+
+TInt CPhoneWatcher::RetrieveTSYName()
+ {
+ LOGCOMMON1("PhoneWatcher : RetrieveTSYName()");
+ TRAPD(error, DoRetrieveTSYNameL());
+ return error;
+ }
+
+TInt CPhoneWatcher::ConnectToETelServer()
+ {
+ LOGCOMMON1("PhoneWatcher : ConnectToETelServer()");
+ return ETel().Connect();
+ }
+
+TInt CPhoneWatcher::LoadPhoneModule()
+ {
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tmpBuf;
+ tmpBuf.Copy(iTSYName);
+ LOGCOMMON1("PhoneWatcher : LoadPhoneModule()");
+ LOGCOMMON2("TSY Name to load is %S",&tmpBuf);
+#endif
+
+ return ETel().LoadPhoneModule(iTSYName);
+ }
+
+TInt CPhoneWatcher::ConnectToPhone()
+ {
+ LOGCOMMON1("PhoneWatcher : ConnectToPhone()");
+ TInt error;
+
+ RTelServer::TPhoneInfo phoneInfo;
+
+ // Get the number of phones
+ TInt phoneCount = 0;
+ error = ETel().EnumeratePhones(phoneCount);
+ if (error < KErrNone)
+ {
+ LOGCOMMON2("PhoneWatcher : Failed to enumerate phones (%d)", error);
+ return error;
+ }
+
+ LOGCOMMON2("PhoneWatcher : Counted %d 'phones'", phoneCount);
+
+ // Iterate through all the phones
+ for(TInt i=0; i<phoneCount; i++)
+ {
+ // Get the TSY name for the phone
+ TName matchTsyName;
+
+ error = ETel().GetTsyName(i, matchTsyName);
+ if (error < KErrNone)
+ {
+ LOGCOMMON2("PhoneWatcher : Getting TSY name failed (%d)", error);
+ return error;
+ }
+
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tmpMatchTsyName;
+ tmpMatchTsyName.Copy(matchTsyName);
+ LOGCOMMON3("PhoneWatcher : TSY for phone %d is '%S'", i, &tmpMatchTsyName);
+#endif
+
+ // See if the phone belongs to the TSY
+ if (matchTsyName.CompareF(iTSYName) == 0)
+ {
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tsyNameBuf;
+ tsyNameBuf.Copy(iTSYName);
+ LOGCOMMON3("PhoneWatcher : %S is a match for CommDb TSY: %S", &tmpMatchTsyName, &tsyNameBuf);
+#endif
+
+ error = ETel().GetPhoneInfo(i, phoneInfo);
+ if (error < KErrNone)
+ {
+ LOGCOMMON2("PhoneWatcher : Getting phone info failed (%d)", error);
+ return error;
+ }
+ break;
+ }
+ }
+
+ // Connect to the specified phone
+ error = Phone().Open(ETel(), phoneInfo.iName);
+ if (error < KErrNone)
+ {
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tmpBuf;
+ tmpBuf.Copy(phoneInfo.iName);
+ LOGCOMMON3("PhoneWatcher : Open phone %S failed (%d)", &tmpBuf, error);
+#endif
+ return error;
+ }
+
+#ifdef _WATCHER_LOGGING_ENABLED
+ TBuf8<256> tmpBuf;
+ tmpBuf.Copy(phoneInfo.iName);
+ LOGCOMMON2("PhoneWatcher : Opened 'phone' %S", &tmpBuf);
+#endif
+
+ // Indicate we're connected and to move to next state.
+ return error;
+ }
+
+//
+//
+//
+
+void CPhoneWatcher::DoRetrieveTSYNameL()
+ {
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+ CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
+#else
+ CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
+#endif
+ CleanupStack::PushL(db);
+
+ CMDBField<TUint32>* globalSettingsField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
+ CleanupStack::PushL(globalSettingsField);
+ globalSettingsField->SetRecordId(1);
+ globalSettingsField->LoadL(*db);
+ TUint32 modemId = *globalSettingsField;
+ CleanupStack::PopAndDestroy(globalSettingsField);
+
+ CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
+ CleanupStack::PushL(tsyField);
+ tsyField->SetRecordId(modemId);
+ tsyField->SetMaxLengthL(KMaxTextLength);
+ tsyField->LoadL(*db);
+ iTSYName = *tsyField;
+ CleanupStack::PopAndDestroy(tsyField);
+
+
+ // Strip any file extension
+ TInt pos = iTSYName.LocateReverse('.');
+ if (pos >= 0)
+ iTSYName = iTSYName.Left(pos);
+
+#ifdef WATCHER_TESTING
+ {
+ TTime now;
+ now.UniversalTime();
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory, KUidTestProp_ModemTableRefreshed.iUid, I64LOW(now.Int64())));
+ }
+#endif
+
+ CleanupStack::PopAndDestroy(); // db or commsDatabase
+ }
+
+EXPORT_C void CPhoneWatcher::PhoneIsOff()
+ {
+ Cancel();
+ Reset(); // Kill phone resources
+#ifdef _DEBUG
+ TRAPD(err, WaitForPhoneToPowerUpL());
+ __ASSERT_DEBUG(err == KErrNone, WatcherBasePanic(EGeneral));
+#else
+ TRAP_IGNORE(WaitForPhoneToPowerUpL());
+#endif
+ }
+
+EXPORT_C void CPhoneWatcher::HandleModemChangedL()
+//
+// Called when the commsdb modem record has changed. Must
+// re-read the current modem and attempt to reinitialise the watcher
+// using this new modem.
+//
+ {
+#ifdef WATCHER_TESTING
+ {
+ TTime now;
+ now.UniversalTime();
+ // State set to ETrue/EFalse
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory, KUidTestProp_ModemRecordChanged.iUid, I64LOW(now.Int64())));
+ }
+#endif
+
+ Cancel();
+
+ // Kill phone resources
+ Reset();
+
+ // Start us going again. This will (in turn)
+ // re-read the comms database. NOTE: Our state has been set to
+ // 'EPhoneStateRetrievingTsyName' by Reset()
+ RequestNextState();
+ }
+