coreapplicationuis/Rfs/src/rfsConnectionObserver.cpp
changeset 0 2e3d3ce01487
child 18 0818dd463d41
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/coreapplicationuis/Rfs/src/rfsConnectionObserver.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,465 @@
+/*
+* Copyright (c) 2006-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: 
+*   Implements CRfsPdpObserver class.
+*
+*
+*/
+
+// SYSTEM INCLUDES
+#include <rfs.rsg>                      
+#include <PSVariables.h>
+#include <AknWaitDialog.h>
+#include <featmgr.h>
+#include <centralrepository.h>
+#include <AknWaitDialog.h>
+#include <pdpcontextmanagerpskeys.h>
+#include <pdpcontextmanagerinternalcrkeys.h>
+
+// P&S KEYS FROM SIP & PDP CONNECTION
+#include <e32property.h>
+#include <pdpcontextmanagerpskeys.h>
+#include <sipsystemstatemonitorpskeys.h>
+
+// USER INCLUDES
+#include "rfsConnectionObserver.h"
+#include "RfsTraces.h"
+
+// CONSTANTS
+const TInt KRfsAlwaysOnDisabled     = 0;
+const TInt KRfsAlwaysOnEnabled      = 1;
+
+
+// ---------------------------------------------------------------------------
+// two phased constructor
+// ---------------------------------------------------------------------------
+CRfsConnectionObserver* CRfsConnectionObserver::NewLC()
+    {
+    TRACES("CRfsConnectionObserver::NewLC()");
+    
+    CRfsConnectionObserver* self = new( ELeave ) CRfsConnectionObserver;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    
+    TRACES("CRfsConnectionObserver::NewLC(): End");
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// second phased constructor
+// ---------------------------------------------------------------------------
+void CRfsConnectionObserver::ConstructL()
+    {
+    TRACES("CRfsConnectionObserver::ConstructL()");
+    
+    iIsPDPFeatureEnabled = IsAlwaysOnFeatureEnabledL();
+    
+    // We first check whether the required keys are defined or not 
+    // i.e. SIP is there or not and PDP feature is there or not.
+    // Following cases can arise:
+    // 1. SIP present and PDP not defined -- Close the SIP connection (&) proceed with RFS
+    // 2. SIP not defined and PDP present -- Close the PDP connection (&) proceed with RFS
+    // 3. SIP and PDP not defined         -- Proceed to perform the RFS. Here no need to close any connection.
+    // 4. Both defined                    -- Close SIP and PDP connection (&) proceed with RFS  
+    //
+    // OutCome: also record which is present and which is not present. This information will be needed
+    // to set the future displaying of the dialog and to know whomo to send notifications and to whom not.
+    //
+    // If none of the active connections are present then no need to display the dialog. 
+    // 
+    // Here we need to inform the outside world (CRfsHandler) that we don't need to call rest of the methods
+    // related to active connections closing operations if the third case is present.
+    // The methods are:
+    //      1. CloseAlwaysOnConnectionL()
+    //      2. ReOpenConnection()
+    
+    TInt val(KErrNone);
+    User::LeaveIfError( iSIPProperty.Attach(KPSSipRfsUid, KSipRfsState));
+    TInt err = iSIPProperty.Get(KPSSipRfsUid, KSipRfsState, val);
+    if (KErrNotFound == err)
+        {
+        // Record that SIP connection is not present
+        iIsSIPConnectionsPresent = EFalse;
+        }
+    
+    // No need to have a similar check for the PDP as the following boolean is sufficient
+    if(iIsPDPFeatureEnabled)
+        {
+        User::LeaveIfError( iPDPProperty.Attach(KPDPContextManager2,KPDPContextManagerFactorySettingsReset ) );
+        }
+    
+    // Following is the condition used to record that the dialog needs to be displayed
+    // and the closing of the connections is possible
+    if (iIsSIPConnectionsPresent || iIsPDPFeatureEnabled)
+        {
+        iIsDialogNeedToBeDisplayed = ETrue;
+        iIsClosingConnectionsApplicable = ETrue;
+        }
+    
+    // After finding out which type of connections need RFS notifications, we will 
+    // proceed further to create a common dialog. This will be a wait for dialog which will be 
+    // of synchrnous type and can only be closed inside the RunL() of this active class.
+    // Provisions needed to be added to know whether this dialog needs resetting the pointer,
+    // this will be the case when dialog is actually started using 'ExecuteLD()', 
+    // Otherwise we need to delete this dialog and reset the pointer to NULL.
+    if (iIsDialogNeedToBeDisplayed)
+        {
+        iWaitDialog = new( ELeave ) CAknWaitDialog(reinterpret_cast<CEikDialog**>( &iWaitDialog ) );
+        }
+   
+    // Now we proceed further to setting of the next state i,e, enter the state machine of this active object
+    // which will start from closing of the active connections and proceed to close the other connections
+    // serially in a state wise manner.
+    // N.B the states are put in order and should be maintained. High Priority
+    //
+    // As soon as 'iStatus' changes we will go to RunL() to close the SIP connection
+    // and hence forth take up the activity of closing PDP connection.
+    if (iIsSIPConnectionsPresent)
+        {
+        iState =  ESipConnectionClose;
+        }
+    else if (iIsPDPFeatureEnabled)
+        {
+        iState =  EPdpConnectionClose;
+        }
+    
+    // After setting the state machine i.e. proper entry point into the RunL()
+    // we will give an asynchronous listening and publishing request to the keys.  
+    if (iIsSIPConnectionsPresent || iIsPDPFeatureEnabled)
+        {
+        Subscribe();
+        }
+    
+    TRACES("CRfsConnectionObserver::ConstructL(): End");
+    }
+
+// ---------------------------------------------------------------------------
+// C++ constructor
+// ---------------------------------------------------------------------------
+CRfsConnectionObserver::CRfsConnectionObserver():CActive( EPriorityStandard )
+    {
+    TRACES("CRfsConnectionObserver::CRfsConnectionObserver()");
+
+    iIsSIPConnectionsPresent = ETrue;
+    iIsPDPFeatureEnabled = ETrue;
+    iIsWaitForDialogExecuted = EFalse;
+    iIsDialogNeedToBeDisplayed = EFalse;
+    iIsSipInformedForClosingAllConnection = EFalse;
+    iIsPDPInformedforClosingAllConnection = EFalse;
+    iIsClosingConnectionsApplicable = EFalse;
+    
+    CActiveScheduler::Add( this );
+    
+    TRACES("CRfsConnectionObserver::CRfsConnectionObserver(): End");
+    }
+             
+// ---------------------------------------------------------------------------
+// C++ destructor
+// ---------------------------------------------------------------------------
+CRfsConnectionObserver::~CRfsConnectionObserver()
+    {
+    TRACES("CRfsConnectionObserver::~CRfsConnectionObserver()");
+    Cancel();
+    TRACES("CRfsConnectionObserver::~CRfsConnectionObserver(): End");
+    }
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::CloseAlwaysOnConnectionL
+// ---------------------------------------------------------------------------
+TBool CRfsConnectionObserver::CloseAlwaysOnConnectionL()
+    {
+    TRACES("CRfsConnectionObserver::CloseAlwaysOnConnectionL()");
+    
+    if (iIsClosingConnectionsApplicable == EFalse)
+        {
+        // pretend that we have dsplayed the dialog and closed all the active connections
+        return ETrue;
+        }
+
+    // only perform the following operation if the 'iIsClosingConnectionsApplicable' is ETrue 
+    iAllConnectionClosed = EFalse;
+      
+    // Send P&S notification to SIP that RFS has started
+    TInt err(KErrNone);
+    if (iIsSIPConnectionsPresent && iState == ESipConnectionClose)
+        {
+        err = iSIPProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsStarted );
+        iIsSipInformedForClosingAllConnection = ETrue;
+        }
+    else if (iIsPDPFeatureEnabled && iState == EPdpConnectionClose)
+        {
+        err = iPDPProperty.Set(KPDPContextManager2,KPDPContextManagerFactorySettingsReset,EPDPContextManagerFactorySettingsResetStart );
+        iIsPDPInformedforClosingAllConnection = ETrue;
+        }
+    
+    
+    // Leave from here is there is any error setting the intial handshake information
+    // This means that RFS has failed as there was some problem setting the P&S keys
+    User::LeaveIfError(err);
+    if(err != KErrNone)
+        {
+        TRACES1("CRfsConnectionObserver::CloseAlwaysOnConnectionL(): Err = %d", err);
+        // This means that the RFS has failed
+        return EFalse; 
+        }
+    
+    // we set the flag to indicate ExecuteLD is called and the dialog needs to be
+    // dismissed from within the RunL()
+    iIsWaitForDialogExecuted = ETrue;
+    // Start displaying the dialog which will then be closed form the RunL()
+    // Here the code execution blocks and we will proceed further only when 
+    // this dialog is canceled
+    err = iWaitDialog->ExecuteLD( R_CLOSING_CONNECTIONS );
+    
+    
+    // following is the case when the user presses the Cancel button from the wait 
+    // for dialog and in that case we need to resend the notificaiton of RFS failed
+    // to whom all we have told previous of this to close the RFS connection
+    if (err == EEikBidCancel)
+        {
+        if (iIsSipInformedForClosingAllConnection)
+            {
+            err = iSIPProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsFailed );
+            }
+        if (iIsPDPInformedforClosingAllConnection)
+            {
+            iPDPProperty.Set(KPDPContextManager2,KPDPContextManagerFactorySettingsReset,EPDPContextManagerFactorySettingsResetStop);
+            }
+        }
+    return iAllConnectionClosed;
+    }
+
+void CRfsConnectionObserver::ReportRfsCompletionToSip()
+    {
+    TRACES("CRfsConnectionObserver::ReportRfsCompletionToSip()");
+    
+    // Only perform the following operation if the 'iIsClosingConnectionsApplicable' 
+    if (!iIsClosingConnectionsApplicable)
+        {
+        // Pretend that we have re-opened all the closed connections and return doinng nothing
+        return;
+        }
+    if (iIsSipInformedForClosingAllConnection)
+        {
+        iSIPProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsCompleted );
+        }
+    
+    TRACES("CRfsConnectionObserver::ReportRfsCompletionToSip(): End");
+    }
+
+void CRfsConnectionObserver::ReportRfsFailureToSip()
+    {
+    TRACES("CRfsConnectionObserver::ReportRfsFailureToSip()");
+    
+    // Only perform the following operation if the 'iIsClosingConnectionsApplicable' 
+    if (!iIsClosingConnectionsApplicable)
+        {
+        // Pretend that we have re-opened all the closed connections and return doinng nothing
+        return;
+        }
+    if (iIsSipInformedForClosingAllConnection)
+        {
+        iSIPProperty.Set(KPSSipRfsUid, KSipRfsState, ESipRfsFailed );
+        }
+    
+    TRACES("CRfsConnectionObserver::ReportRfsFailureToSip(): End");
+    }
+
+void CRfsConnectionObserver::ReOpenPDPConnection()
+    {
+    TRACES("CRfsConnectionObserver::ReOpenPDPConnection()");
+    
+    // Only perform the following operation if the 'iIsClosingConnectionsApplicable' 
+    if (!iIsClosingConnectionsApplicable)
+        {
+        // Pretend that we have re-opened all the closed connections and return doinng nothing
+        return;
+        }
+    
+    if (iIsPDPInformedforClosingAllConnection )
+         {
+         iPDPProperty.Set(KPDPContextManager2,KPDPContextManagerFactorySettingsReset,EPDPContextManagerFactorySettingsResetStop );
+         }
+    
+    TRACES("CRfsConnectionObserver::ReOpenPDPConnection(): End");
+    }
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::RunL
+// ---------------------------------------------------------------------------
+void CRfsConnectionObserver::RunL()
+    {
+    // First call this is to enroll for the next handshake information to be recieved either from SIP or PDP
+   Subscribe(); 
+    
+    switch(iState)
+        {
+        case ESipConnectionClose:
+            {
+            // Send P&S message to SIP 
+            TInt val;
+            TInt err = iSIPProperty.Get(KPSSipRfsUid, KSipRfsState, val);
+            if ( err == KErrNone && val == ESipRfsEventProcessingCompleted)
+                {
+                if (iIsWaitForDialogExecuted && !iIsPDPFeatureEnabled)
+                    {
+                    // set the information that we have closed all the active connections
+                    // here itself because the PDP connection/feature doen't exist
+                    iAllConnectionClosed = ETrue;
+                    DismissWaitDialog();
+                    }
+                
+                if (iIsPDPFeatureEnabled)
+                    {
+                    iPDPProperty.Set(KPDPContextManager2,KPDPContextManagerFactorySettingsReset,EPDPContextManagerFactorySettingsResetStart );
+                    
+                    // change the state to the next from within this as we are done with closing the SIP connection
+                    iState = EPdpConnectionClose;
+                    //
+                    // Under following cases the 'iIsPDPInformedforClosingAllConnection' will be set
+                    //
+                    // CASE 1:
+                    //          When from within CloseAlwaysOnConnectionL we inform the PDP to 
+                    //          close its connection, that time this will be set.
+                    // CASE 2: 
+                    //          The other case covers when the SIP exists, then this flag will be set 
+                    //          when we come to RunL straight to this  switch-case after just previous to
+                    //          switch-case being of closing All the SIP active connections.
+                    //
+                    // RATIONALE: (behind the use of following flag):
+                    //            Setting of this flag will actually help us in the case when
+                    //            the user cancels the PDP closing connections
+                    iIsPDPInformedforClosingAllConnection = ETrue;
+                    }
+                TRACES1("CRfsConnectionObserver::RunL(): iPDPProperty.Set returned Err = %d", err);
+                }
+            break;
+            }
+        case EPdpConnectionClose:
+            {
+            // When we reach here we should assume that:
+            //      1. the WAIT FOR dialog is being tothe user of the device 
+            //      2. If SIP existed then it has successfully closed all its active connections
+            //               
+            // What needs to be done at this point of time is to :
+            //      1. Check of what message has been published to the 'KPDPContextManagerFactorySettingsReset' key
+            //      2. If the PDP has replied with all its active connections closed then we should close the dialog 
+            //         and set the information that we have closed all the active connections including SIP if it existed
+            //         at the time when the user requested for an RFS 
+             
+            TInt val;
+            TInt err = iPDPProperty.Get(KPDPContextManager2,KPDPContextManagerFactorySettingsReset, val);
+            if (err == KErrNone && val == EPDPContextManagerFactorySettingsResetStartReply && iAllConnectionClosed == EFalse )
+                {
+                // The response from PDP of closing all its connections have been recieved 
+                // Now we may proceed to dsmiss the dialog and also set the state to the True for 
+                // all active connections closed
+                iAllConnectionClosed = ETrue;
+                DismissWaitDialog();
+                }
+            }
+        } // end switch-case block
+    }
+
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::IsAlwaysOnFeatureEnabledL
+// ---------------------------------------------------------------------------
+TInt CRfsConnectionObserver::IsAlwaysOnFeatureEnabledL()
+    {
+    TInt alwaysOnEnabled = KRfsAlwaysOnDisabled;
+    if( FeatureManager::FeatureSupported( KFeatureIdAlwaysOnlinePDPContext2 ) )
+        {
+        // Check if always on feature enabled
+        CRepository* cenRep = CRepository::NewLC( KCRUidPDPContextManager );
+        TInt err = cenRep->Get( KPDPContextAlwaysOnEnabled, alwaysOnEnabled );
+        if( err != KErrNone )
+            {
+            alwaysOnEnabled = KRfsAlwaysOnEnabled;
+            }
+        CleanupStack::PopAndDestroy(cenRep); 
+        }
+    return alwaysOnEnabled;
+    }
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::DoCancel
+// ---------------------------------------------------------------------------
+void CRfsConnectionObserver::DoCancel()
+    {
+    TRACES("CRfsConnectionObserver::DoCancel()");
+    
+    if(iIsPDPFeatureEnabled)
+        {
+        iPDPProperty.Cancel();
+        }
+    if(iIsSIPConnectionsPresent)
+        {
+        iSIPProperty.Cancel();
+        }
+
+    DismissWaitDialog();
+    
+    TRACES("CRfsConnectionObserver::DoCancel(): End");
+    }
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::Subscribe
+// ---------------------------------------------------------------------------
+void CRfsConnectionObserver::Subscribe()
+    {
+    switch(iState)
+        {
+        case ESipConnectionClose: 
+            {
+            // SIP connection first [Always]
+            iSIPProperty.Subscribe(iStatus);
+            break;
+            }
+        case EPdpConnectionClose:
+            {
+            iPDPProperty.Subscribe(iStatus);
+            break;
+            }
+        }
+    SetActive();
+    }
+
+// ---------------------------------------------------------------------------
+// CRfsConnectionObserver::DismissWaitDialog
+// ---------------------------------------------------------------------------
+void CRfsConnectionObserver::DismissWaitDialog()
+    {
+    TRACES("CRfsConnectionObserver::DismissWaitDialog()");
+    
+    if ( iWaitDialog && iIsWaitForDialogExecuted)
+        {
+        TRAP_IGNORE( iWaitDialog->ProcessFinishedL() );
+        }
+    
+    // Sanity Check:
+    // It can be a case when dialog was need to be displayed but was not due to some error
+    // this means that the 'iWaitDialog' was constructed but never used and destroyed
+    // i.e. the ExecuteLD() was never called
+    else if(iIsDialogNeedToBeDisplayed && !iIsWaitForDialogExecuted)
+        {
+        delete iWaitDialog;
+        }
+    
+    // Reset the pointer to NULL
+    iWaitDialog = NULL;
+    
+    TRACES("CRfsConnectionObserver::DismissWaitDialog(): End");
+    }
+