Application-level roaming (ALR) was introduced in S60 3rd Edition, Feature Pack 2. It enables your application to roam to use the best available data connection while operational. For more information, see Destination networks.
Important implementation considerations include:
There is no SDK method for WLAN scanning. Your application should use Connection Monitor Server API to request the list of available IAPs or network names (in the case of a WLAN these are SSIDs). Connection Monitor Server API also provides notifications about changes in the IAP availability list.
Handovers between GPRS and WCDMA radio networks take a long time (from 15 seconds to 2 minutes) and sometimes fail completely. You should use long application level timers (if any) and maintain a responsive UI. Note that handovers between GPRS and WCDMA cannot be controlled by the S60 platform (except with fixed settings). The control logic is in the cellular modem.
In ALR, the transfer from one connection to another always introduces an IP address change and a break in data connection (even with make-before-break when the break is really short). This is because the sockets need to be closed and re-opened. This may be problematic for the applications that maintain a stateful connection with a server in the network. The workaround for a break is to open a new RConnection handle when receiving PreferredCarrierAvailable() and establishing the server connection using that (if the application protocol allows such operation). When that is done and new sockets are created for the new RConnection, the original RConnection can be closed. There’s no workaround for the IP address change.
To use application-level roaming:
Initiate an Internet connection using the Connection Manager API and the Internet destination network. In this example it is assumed that the best available IAP for Internet is GPRS.
RConnection handle is returned to the application.
Register for mobility API sending NewL(RConnection handle, MMobilityProtocolResp&) to the Connection Manager API.
Link layer is now ready for the application.
Use RConnection
to open RSockets with RConnection
handle.
RSocket handle is returned to the application.
Initiate normal socket communication to the Sockets Client API. This data transfer uses GPRS.
Some time passes at this point of the process.
A WLAN IAP becomes available. The Connection Manager API sends PreferredCarrierAvailable(old IAP, new IAP, is upgrade, not seamless) to the application.
The application decides to switch to the better IAP. It closes the old socket using the Sockets Client API.
Send MigrateToPreferredCarrier() to the Connection Manager API.
Note: The application can also IgnorePreferredCarrier(). In that case it would just keep using the existing socket.
The connection is moved in the Connection Manager API. The WLAN IAP is activated and RConnection handle is moved from the GPRS interface to WLAN.
NewCarrierActive(new IAP) is returned to the application.
The WLAN IAP is now ready to be used.
Use Sockets Client API to open RSockets with RConnection handle. This data transfer uses WLAN.
Transfer data using the Sockets Client API to confirm that the connection works.
Send NewCarrierAccepted() to the Connection Manager API. This is the point of no return.
Continue transferring data using the Sockets Client API. This data transfer uses WLAN.
The following figure illustrates the process.
Figure: Application-level roaming
The following code snippets illustrate various parts of the process.
The class (for example, CALRApplication) that wants to use the Mobility messages declares:
the interface MMobilityProtocolResp
class member CActiveCommsMobilityApiExt, e.g. iMobility. CALRApplication is the one likely to have a RConnection member
#include <comms-infras/cs_mobility_apiext.h> class CALRApplication : public CActive, public MMobilityProtocolResp { ... public: // From MMobilityProtocolResp void PreferredCarrierAvailable( TAccessPointInfo aOldAPInfo, TAccessPointInfo aNewAPInfo, TBool aIsUpgrade, TBool aIsSeamless ); void NewCarrierActive( TAccessPointInfo aNewAPInfo, TBool aIsSeamless ); void Error( TInt aError ); ... private: // Data ... RConnection iConnection; CActiveCommsMobilityApiExt* iMobility; };
When the connection starts, iMobility is created and it registers the connection to receive mobility messages.
iMobility = CActiveCommsMobilityApiExt::NewL( iConnection, *this );
When a preferred IAP becomes available, the implementation of CALRApplication::PreferredCarrierAvailable is called. MigrateToPreferredCarrier Mobility message is sent to the middleware in order to roam to this preferred IAP.
void CALRApplication::PreferredCarrierAvailable( TAccessPointInfo aOldAPInfo, TAccessPointInfo aNewAPInfo, TBool aIsUpgrade, TBool aIsSeamless ) { // aOldAPInfo contains the current IAP used by the connection. // aNewAPInfo contains the newly available IAP that can be used by the connection. if ( aIsSeamless ) { // It is Seamless. E.g. Mobile IP enabled. } else { // sockets used by the connection should be closed here. // We ask to migrate to the Preferred Carrier. iMobility->MigrateToPreferredCarrier(); } }
Once the connection roamed to the new IAP, the implementation of CALRApplication::NewCarrierActive is called. The application reopens its sockets on the connection. If the sockets' connection is fine, the application sends the NewCarrierAccepted Mobility message to the middleware.
void CALRApplication::NewCarrierActive( TAccessPointInfo aNewAPInfo, TBool aIsSeamless ) { // aNewAPInfo contains the newly started IAP used now by the connection. if ( aIsSeamless ) { // It is Seamless. E.g. Mobile IP enabled. } else { // sockets used by the connection should be reopened here. // We accept the new IAP. iMobility->NewCarrierAccepted(); } }
The following S60 APIs are used to implement application-level roaming:
Sockets Client API (sometimes called ESOCK after its library name) is the API for all IP-based socket communication. It remains unchanged, but applications need to be ready to close and open sockets at certain times to roam for a better connection.
Connection Manager API (often referred to as RConnection API because Symbian does not collect APIs into similar logical entities as the S60 platform does) is a collection of Symbian's connection management-related functionalities provided by Sockets Client API. It contains several extensions and one of them is the mobility extension. The term "mobility API" actually refers to the mobility extensions that are part of Connection Manager API and defined in header cs_mobility_apiext.h. With the so-called mobility API the client application can register for mobility events, receive information about preferred connections, indicate whether to switch to a new connection or ignore it. In short, it enables ALR for the applications.
Communications Infrastructure ESOCK classes are described in the C++ component reference of the Symbian OS Library.
The mobility extension functionality of the Connection Manager API (defined in header file cs_mobility_apiext.h) is provided by classes MMobilityProtocolResp and CActiveCommsMobilityApiExt.
Methods that must be implemented by client (class MMobilityProtocolResp):
virtual void PreferredCarrierAvailable(TAccessPointInfo aOldAP, TAccessPointInfo aNewAP, TBool aIsUpgrade, TBool aIsSeamless ); This method is called by the middleware to notify a client about a new preferred connection.
virtual void NewCarrierActive(TAccessPointInfo aNewAP, TBool aIsSeamless ); This method is called by the middleware to notify a client that a preferred connection has been activated.
virtual void Error(TInt aError); This method is called by middleware to notify that there are no suitable connections available.
Methods provided by ESock (class CActiveCommsMobilityApiExt):
void MigrateToPreferredCarrier(); Client can indicate that it wants to start using a new preferred connection as a response to PreferredCarrierAvailable().
void IgnorePreferredCarrier(); Client can indicate that it doesn’t want to use a new preferred connection as a response to PreferredCarrierAvailable().
void NewCarrierAccepted(); Client indicates that a new connection is working for it.
void NewCarrierRejected(); Client indicates that a new connection is not working and it wants to use another connection. In this case it receives PreferredCarrierAvailable() again with probably the original connection as a preferred one. The non-working IAP is blacklisted for that client and not suggested again.
Connection Monitor Server API provides availability information. It is possible to query available SNAPs, IAPs, radio bearers or WLAN SSIDs. It also offers various information about active connections.