42 #include "qnetworkconfigmanager_s60_p.h" |
42 #include "qnetworkconfigmanager_s60_p.h" |
43 |
43 |
44 #include <commdb.h> |
44 #include <commdb.h> |
45 #include <cdbcols.h> |
45 #include <cdbcols.h> |
46 #include <d32dbms.h> |
46 #include <d32dbms.h> |
|
47 #include <QEventLoop> |
|
48 #include <QTimer> |
|
49 #include <QTime> // For randgen seeding |
|
50 #include <QtCore> // For randgen seeding |
|
51 |
|
52 // #define QT_BEARERMGMT_CONFIGMGR_DEBUG |
|
53 |
|
54 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG |
|
55 #include <QDebug> |
|
56 #endif |
47 |
57 |
48 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
58 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
49 #include <cmdestination.h> |
59 #include <cmdestination.h> |
50 #include <cmconnectionmethod.h> |
60 #include <cmconnectionmethod.h> |
51 #include <cmconnectionmethoddef.h> |
61 #include <cmconnectionmethoddef.h> |
62 |
72 |
63 static const int KValueThatWillBeAddedToSNAPId = 1000; |
73 static const int KValueThatWillBeAddedToSNAPId = 1000; |
64 static const int KUserChoiceIAPId = 0; |
74 static const int KUserChoiceIAPId = 0; |
65 |
75 |
66 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate() |
76 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate() |
67 : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0), iFirstUpdate(true), iInitOk(true) |
77 : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0), |
|
78 iFirstUpdate(true), iInitOk(true), iIgnoringUpdates(false), |
|
79 iTimeToWait(0), iIgnoreEventLoop(0) |
68 { |
80 { |
69 CActiveScheduler::Add(this); |
81 CActiveScheduler::Add(this); |
|
82 |
|
83 // Seed the randomgenerator |
|
84 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); |
|
85 iIgnoreEventLoop = new QEventLoop(this); |
70 |
86 |
71 registerPlatformCapabilities(); |
87 registerPlatformCapabilities(); |
72 TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP)); |
88 TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP)); |
73 if (error != KErrNone) { |
89 if (error != KErrNone) { |
74 iInitOk = false; |
90 iInitOk = false; |
98 cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; |
114 cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; |
99 cpPriv->roamingSupported = false; |
115 cpPriv->roamingSupported = false; |
100 cpPriv->manager = this; |
116 cpPriv->manager = this; |
101 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv); |
117 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv); |
102 userChoiceConfigurations.insert(cpPriv->id, ptr); |
118 userChoiceConfigurations.insert(cpPriv->id, ptr); |
103 |
|
104 updateConfigurations(); |
119 updateConfigurations(); |
105 updateStatesToSnaps(); |
120 updateStatesToSnaps(); |
106 |
|
107 updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans) |
121 updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans) |
108 |
|
109 // Start monitoring IAP and/or SNAP changes in Symbian CommsDB |
122 // Start monitoring IAP and/or SNAP changes in Symbian CommsDB |
110 startCommsDatabaseNotifications(); |
123 startCommsDatabaseNotifications(); |
111 iFirstUpdate = false; |
124 iFirstUpdate = false; |
112 } |
125 } |
113 |
126 |
114 QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() |
127 QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() |
115 { |
128 { |
116 Cancel(); |
129 Cancel(); |
117 |
130 |
118 QList<QString> configIdents = snapConfigurations.keys(); |
131 foreach (const QString &oldIface, snapConfigurations.keys()) { |
119 foreach(QString oldIface, configIdents) { |
|
120 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface); |
132 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface); |
121 priv->isValid = false; |
133 priv->isValid = false; |
122 priv->id.clear(); |
134 priv->id.clear(); |
123 } |
135 } |
124 |
136 |
125 configIdents = accessPointConfigurations.keys(); |
137 foreach (const QString &oldIface, accessPointConfigurations.keys()) { |
126 foreach(QString oldIface, configIdents) { |
|
127 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface); |
138 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface); |
128 priv->isValid = false; |
139 priv->isValid = false; |
129 priv->id.clear(); |
140 priv->id.clear(); |
130 } |
141 } |
131 |
142 |
132 configIdents = userChoiceConfigurations.keys(); |
143 foreach (const QString &oldIface, userChoiceConfigurations.keys()) { |
133 foreach(QString oldIface, configIdents) { |
|
134 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = userChoiceConfigurations.take(oldIface); |
144 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = userChoiceConfigurations.take(oldIface); |
135 priv->isValid = false; |
145 priv->isValid = false; |
136 priv->id.clear(); |
146 priv->id.clear(); |
137 priv->manager = 0; |
147 priv->manager = 0; |
138 } |
148 } |
164 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
174 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
165 capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming; |
175 capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming; |
166 capFlags |= QNetworkConfigurationManager::ForcedRoaming; |
176 capFlags |= QNetworkConfigurationManager::ForcedRoaming; |
167 #endif |
177 #endif |
168 capFlags |= QNetworkConfigurationManager::DataStatistics; |
178 capFlags |= QNetworkConfigurationManager::DataStatistics; |
|
179 capFlags |= QNetworkConfigurationManager::NetworkSessionRequired; |
169 } |
180 } |
170 |
181 |
171 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() |
182 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() |
172 { |
183 { |
173 if (!iInitOk || iUpdateGoingOn) { |
184 if (!iInitOk || iUpdateGoingOn) { |
191 |
202 |
192 void QNetworkConfigurationManagerPrivate::updateConfigurationsL() |
203 void QNetworkConfigurationManagerPrivate::updateConfigurationsL() |
193 { |
204 { |
194 QList<QString> knownConfigs = accessPointConfigurations.keys(); |
205 QList<QString> knownConfigs = accessPointConfigurations.keys(); |
195 QList<QString> knownSnapConfigs = snapConfigurations.keys(); |
206 QList<QString> knownSnapConfigs = snapConfigurations.keys(); |
196 |
207 |
197 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
208 #ifdef SNAP_FUNCTIONALITY_AVAILABLE |
198 // S60 version is >= Series60 3rd Edition Feature Pack 2 |
209 // S60 version is >= Series60 3rd Edition Feature Pack 2 |
199 TInt error = KErrNone; |
210 TInt error = KErrNone; |
200 |
211 |
201 // Loop through all IAPs |
212 // Loop through all IAPs |
348 } |
359 } |
349 CleanupStack::PopAndDestroy(pDbTView); |
360 CleanupStack::PopAndDestroy(pDbTView); |
350 #endif |
361 #endif |
351 updateActiveAccessPoints(); |
362 updateActiveAccessPoints(); |
352 |
363 |
353 foreach (QString oldIface, knownConfigs) { |
364 foreach (const QString &oldIface, knownConfigs) { |
354 //remove non existing IAP |
365 //remove non existing IAP |
355 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface); |
366 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface); |
356 priv->isValid = false; |
367 priv->isValid = false; |
357 if (!iFirstUpdate) { |
368 if (!iFirstUpdate) { |
358 QNetworkConfiguration item; |
369 QNetworkConfiguration item; |
359 item.d = priv; |
370 item.d = priv; |
360 emit configurationRemoved(item); |
371 emit configurationRemoved(item); |
361 } |
372 } |
362 // Remove non existing IAP from SNAPs |
373 // Remove non existing IAP from SNAPs |
363 QList<QString> snapConfigIdents = snapConfigurations.keys(); |
374 foreach (const QString &iface, snapConfigurations.keys()) { |
364 foreach (QString iface, snapConfigIdents) { |
|
365 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface); |
375 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface); |
366 // => Check if one of the IAPs of the SNAP is active |
376 // => Check if one of the IAPs of the SNAP is active |
367 for (int i=0; i<priv2->serviceNetworkMembers.count(); i++) { |
377 for (int i=0; i<priv2->serviceNetworkMembers.count(); i++) { |
368 if (priv2->serviceNetworkMembers[i]->numericId == priv->numericId) { |
378 if (priv2->serviceNetworkMembers[i]->numericId == priv->numericId) { |
369 priv2->serviceNetworkMembers.removeAt(i); |
379 priv2->serviceNetworkMembers.removeAt(i); |
370 break; |
380 break; |
371 } |
381 } |
372 } |
382 } |
373 } |
383 } |
374 } |
384 } |
375 foreach (QString oldIface, knownSnapConfigs) { |
385 foreach (const QString &oldIface, knownSnapConfigs) { |
376 //remove non existing SNAPs |
386 //remove non existing SNAPs |
377 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface); |
387 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface); |
378 priv->isValid = false; |
388 priv->isValid = false; |
379 if (!iFirstUpdate) { |
389 if (!iFirstUpdate) { |
380 QNetworkConfiguration item; |
390 QNetworkConfiguration item; |
617 } |
627 } |
618 } |
628 } |
619 } |
629 } |
620 |
630 |
621 // Make sure that state of rest of the IAPs won't be Active |
631 // Make sure that state of rest of the IAPs won't be Active |
622 foreach (QString iface, inactiveConfigs) { |
632 foreach (const QString &iface, inactiveConfigs) { |
623 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
633 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
624 if (priv.data()) { |
634 if (priv.data()) { |
625 // Configuration is either Defined or Discovered |
635 // Configuration is either Defined or Discovered |
626 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered); |
636 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered); |
627 } |
637 } |
663 } |
673 } |
664 } |
674 } |
665 } |
675 } |
666 |
676 |
667 // Make sure that state of rest of the IAPs won't be Discovered or Active |
677 // Make sure that state of rest of the IAPs won't be Discovered or Active |
668 foreach (QString iface, unavailableConfigs) { |
678 foreach (const QString &iface, unavailableConfigs) { |
669 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
679 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
670 if (priv.data()) { |
680 if (priv.data()) { |
671 // Configuration is Defined |
681 // Configuration is Defined |
672 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); |
682 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); |
673 } |
683 } |
683 } |
693 } |
684 |
694 |
685 void QNetworkConfigurationManagerPrivate::updateStatesToSnaps() |
695 void QNetworkConfigurationManagerPrivate::updateStatesToSnaps() |
686 { |
696 { |
687 // Go through SNAPs and set correct state to SNAPs |
697 // Go through SNAPs and set correct state to SNAPs |
688 QList<QString> snapConfigIdents = snapConfigurations.keys(); |
698 foreach (const QString &iface, snapConfigurations.keys()) { |
689 foreach (QString iface, snapConfigIdents) { |
|
690 bool discovered = false; |
699 bool discovered = false; |
691 bool active = false; |
700 bool active = false; |
692 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.value(iface); |
701 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.value(iface); |
693 // => Check if one of the IAPs of the SNAP is discovered or active |
702 // => Check if one of the IAPs of the SNAP is discovered or active |
694 // => If one of IAPs is active, also SNAP is active |
703 // => If one of IAPs is active, also SNAP is active |
796 } |
805 } |
797 } |
806 } |
798 |
807 |
799 void QNetworkConfigurationManagerPrivate::RunL() |
808 void QNetworkConfigurationManagerPrivate::RunL() |
800 { |
809 { |
|
810 if (iIgnoringUpdates) { |
|
811 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG |
|
812 qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently)."); |
|
813 #endif |
|
814 return; |
|
815 } |
801 if (iStatus != KErrCancel) { |
816 if (iStatus != KErrCancel) { |
802 RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int()); |
817 RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int()); |
803 switch (event) { |
818 switch (event) { |
804 // case RDbNotifier::EUnlock: /** All read locks have been removed. */ |
819 case RDbNotifier::EUnlock: /** All read locks have been removed. */ |
805 case RDbNotifier::ECommit: /** A transaction has been committed. */ |
820 case RDbNotifier::ECommit: /** A transaction has been committed. */ |
806 case RDbNotifier::ERollback: /** A transaction has been rolled back */ |
821 case RDbNotifier::ERollback: /** A transaction has been rolled back */ |
807 case RDbNotifier::ERecover: /** The database has been recovered */ |
822 case RDbNotifier::ERecover: /** The database has been recovered */ |
808 // Note that if further database events occur while a client is handling |
823 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG |
809 // a request completion, the notifier records the most significant database |
824 qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int()); |
810 // event and this is signalled as soon as the client issues the next |
825 #endif |
811 // RequestNotification() request. |
826 iIgnoringUpdates = true; |
812 // => Stop recording notifications |
827 // Other events than ECommit get lower priority. In practice with those events, |
813 stopCommsDatabaseNotifications(); |
828 // we delay_before_updating methods, whereas |
814 TRAPD(error, updateConfigurationsL()); |
829 // with ECommit we _update_before_delaying the reaction to next event. |
815 if (error == KErrNone) { |
830 // Few important notes: 1) listening to only ECommit does not seem to be adequate, |
816 updateStatesToSnaps(); |
831 // but updates will be missed. Hence other events are reacted upon too. |
817 } |
832 // 2) RDbNotifier records the most significant event, and that will be returned once |
|
833 // we issue new RequestNotification, and hence updates will not be missed even |
|
834 // when we are 'not reacting to them' for few seconds. |
|
835 if (event == RDbNotifier::ECommit) { |
|
836 TRAPD(error, updateConfigurationsL()); |
|
837 if (error == KErrNone) { |
|
838 updateStatesToSnaps(); |
|
839 } |
|
840 waitRandomTime(); |
|
841 } else { |
|
842 waitRandomTime(); |
|
843 TRAPD(error, updateConfigurationsL()); |
|
844 if (error == KErrNone) { |
|
845 updateStatesToSnaps(); |
|
846 } |
|
847 } |
|
848 iIgnoringUpdates = false; // Wait time done, allow updating again |
818 iWaitingCommsDatabaseNotifications = true; |
849 iWaitingCommsDatabaseNotifications = true; |
819 break; |
850 break; |
820 default: |
851 default: |
821 // Do nothing |
852 // Do nothing |
822 break; |
853 break; |
823 } |
854 } |
824 } |
855 } |
825 |
|
826 if (iWaitingCommsDatabaseNotifications) { |
856 if (iWaitingCommsDatabaseNotifications) { |
827 if (!IsActive()) { |
857 if (!IsActive()) { |
828 SetActive(); |
858 SetActive(); |
829 // Start waiting for new notification |
859 // Start waiting for new notification |
830 ipCommsDB->RequestNotification(iStatus); |
860 ipCommsDB->RequestNotification(iStatus); |
910 // Configuration is either Discovered or Active |
939 // Configuration is either Discovered or Active |
911 changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered); |
940 changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered); |
912 unDiscoveredConfigs.removeOne(ident); |
941 unDiscoveredConfigs.removeOne(ident); |
913 } |
942 } |
914 } |
943 } |
915 foreach (QString iface, unDiscoveredConfigs) { |
944 foreach (const QString &iface, unDiscoveredConfigs) { |
916 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
945 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface); |
917 if (priv.data()) { |
946 if (priv.data()) { |
918 // Configuration is Defined |
947 // Configuration is Defined |
919 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); |
948 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); |
920 } |
949 } |
924 |
953 |
925 default: |
954 default: |
926 // For unrecognized events |
955 // For unrecognized events |
927 break; |
956 break; |
928 } |
957 } |
|
958 } |
|
959 |
|
960 // Waits for 1..4 seconds. |
|
961 void QNetworkConfigurationManagerPrivate::waitRandomTime() |
|
962 { |
|
963 iTimeToWait = (qAbs(qrand()) % 5) * 1000; |
|
964 if (iTimeToWait < 1000) { |
|
965 iTimeToWait = 1000; |
|
966 } |
|
967 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG |
|
968 qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait); |
|
969 #endif |
|
970 QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit())); |
|
971 iIgnoreEventLoop->exec(); |
929 } |
972 } |
930 |
973 |
931 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId) |
974 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId) |
932 { |
975 { |
933 QNetworkConfiguration item; |
976 QNetworkConfiguration item; |