locationsystemui/locationsysui/locsettingsuiservice/locsettingsuiclient/src/locsettingsuiservice.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 11 May 2010 16:36:36 +0300
branchRCL_3
changeset 23 5944cae565c9
parent 0 667063e416a2
permissions -rw-r--r--
Revision: 201017 Kit: 201019

/*
* Copyright (c) 2005-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:  Client side resource handle to the UI Server
*
*/


// System Includes
#include <avkon.hrh>

// User Includes
#include "locsettingsuiservice.h"
#include "loclaunchuiao.h"
#include "locsettingsuiserverinterface.h"

// Constant Declarations
const TInt KNumofConnectAttempts = 200;
    
// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// C++ Default Constructor
// ---------------------------------------------------------------------------
//
RLocSettingsUiService::RLocSettingsUiService()
    :iLaunchAO( NULL ),
    iRequestStatus( NULL ),
    iLaunchType( ELaunchNone ),
    iSrvMonitor( NULL )
    {
    }

// ---------------------------------------------------------------------------
// C++ Destructor
// ---------------------------------------------------------------------------
//
RLocSettingsUiService::~RLocSettingsUiService()
    {
    if( ELaunchNone != iLaunchType )
        {
        CancelLaunchedSettingsUi();
        }   
    }

// ---------------------------------------------------------------------------
// Launch a Settings UI in an ui app server
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchSettingsUiL(
                                    TUid            aImplementationUid,
                                    TInt            aParams,
                                    TRequestStatus& aStatus )
    {
    
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectServerL();
    
    // Store the aStatus variable. This would be used to notify the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Type and the Service state
    iLaunchType = ELaunchNormal;
                      
    TIpcArgs args( aImplementationUid.iUid, aParams );
    
	SendReceive( ELaunchSettings, args, status );
    
    iSrvMonitor = NULL;
    }
    
// ---------------------------------------------------------------------------
// Launch a Settings UI as an embedded application
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchSettingsUiAsEmbeddedAppL(
                                            TUid            aImplementationUid,
                                            TInt            aParams,
                                            TRequestStatus& aStatus )
    {
    
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectChainedAppL( TUid::Uid( KLocSettingsUiServerUid ));
    
    // Store the aStatus variable. This would be used to notfy the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Request Type and the Service state
    iLaunchType = ELaunchEmbedded;  
                      
    TIpcArgs args( aImplementationUid.iUid, aParams );
	SendReceive( ELaunchSettings, args, status );

    iSrvMonitor = CApaServerAppExitMonitor::NewL(*this, 
                                                 *this,
                                                 CActive::EPriorityStandard);
    }

// ---------------------------------------------------------------------------
// Launch a Settings UI in an ui app server
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchSettingsUiL(
                                    TUid            aImplementationUid,
                                    const TDesC&            aParamsString,
                                    TRequestStatus& aStatus )
    {
    
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectServerL();
    
    // Store the aStatus variable. This would be used to notify the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Type and the Service state
    iLaunchType = ELaunchNormal;
                      
    TIpcArgs args( aImplementationUid.iUid, aParamsString.Length(), &aParamsString );
    
	SendReceive( ELaunchSettingsWithString, args, status );
    
    iSrvMonitor = NULL;
    }
    
// ---------------------------------------------------------------------------
// Launch a Settings UI as an embedded application
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchSettingsUiAsEmbeddedAppL(
                                            TUid            aImplementationUid,
                                            const TDesC&            aParamsString,
                                            TRequestStatus& aStatus )
    {
    
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectChainedAppL( TUid::Uid( KLocSettingsUiServerUid ));
    
    // Store the aStatus variable. This would be used to notfy the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Request Type and the Service state
    iLaunchType = ELaunchEmbedded;  
                      
    TIpcArgs args( aImplementationUid.iUid, aParamsString.Length(), &aParamsString );
    
	SendReceive( ELaunchSettingsWithString, args, status );

    iSrvMonitor = CApaServerAppExitMonitor::NewL(*this, 
                                                 *this,
                                                 CActive::EPriorityStandard);
    }
    
// ---------------------------------------------------------------------------
// Cancels a Launched request
// ---------------------------------------------------------------------------
//    
TInt RLocSettingsUiService::CancelLaunchedSettingsUi()
    {
    // If no request is outstanding then this operation is not supported 
    // in this context
    if( ELaunchNone == iLaunchType )
        {
        return KErrNotSupported;
        }
    
    // Issue a Cancel message
    TInt error = SendReceive( ECancelSettings );
    
    if ( error )
        {
        return error;
        }
        
    // Cancel the Active objects Request
    iLaunchAO->Cancel();

    // Delete the Server Exit monitor object before closing the 
    // server session.
    delete iSrvMonitor;
    iSrvMonitor = NULL;        

    // Delete the Server session
    RAknAppServiceBase::Close();
    
    // Set the Launch type so that next launchs will succeed
    iLaunchType = ELaunchNone;
    
    // Sets the Launch 
    // Complete the request with KErrCancel
    TRequestStatus*     status = iRequestStatus;
    User::RequestComplete( status, KErrCancel );
    
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// Launch Positioning Settings UI in an ui app server
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchPosSettingsL(
                                            TRequestStatus& aStatus )
    {
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectServerL();
    
    // Store the aStatus variable. This would be used to notify the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Type and the Service state
    iLaunchType = ELaunchNormal;
    
	SendReceive( ELaunchPosSettings, status );
    
    iSrvMonitor = NULL;
    }
    
// ---------------------------------------------------------------------------
// Launch Positioning Settings UI as an embesdded application
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchPosSettingsAsEmbeddedAppL(
                                                TRequestStatus& aStatus )
    {
    // Check the presence of the Active Object
    if( NULL == iLaunchAO )
        {
        User::Leave( KErrNotFound );
        }
        
    // Check if there is any outstanding requests
    if( ELaunchNone != iLaunchType )
        {
        User::Leave( KErrInUse );
        }
    
    // Create the Server Session
    ConnectChainedAppL( TUid::Uid( KLocSettingsUiServerUid ));
    
    // Store the aStatus variable. This would be used to notfy the caller
    // on completeion of the launch message
    iRequestStatus = &aStatus;  
    *iRequestStatus = KRequestPending;
    
    // Set request outstanding on the Active object
    iLaunchAO->SetRequestOutStandingL();
        
    // Compose the Message and Issue a Launch call to the server
    TRequestStatus&     status = iLaunchAO->GetStatusVariable();
    
    // Set the Launch Request Type and the Service state
    iLaunchType = ELaunchEmbedded;  

	SendReceive( ELaunchPosSettings, status );

    iSrvMonitor = CApaServerAppExitMonitor::NewL(*this, 
                                                 *this,
                                                 CActive::EPriorityStandard);
    }
    
// ---------------------------------------------------------------------------
// Closes an already launched Positioning Settings UI.
// ---------------------------------------------------------------------------
//    
TInt RLocSettingsUiService::ClosePosSettings()
    {
    // If no request is outstanding then this operation is not supported 
    // in this context
    if( ELaunchNone == iLaunchType )
        {
        return KErrNotSupported;
        }
    
    // Issue a Cancel message
    TInt error = SendReceive( ECancelPosSettings );
    
    if ( error )
        {
        return error;
        }
        
    // Cancel the Active objects Request
    iLaunchAO->Cancel();

    // Delete the Server Exit monitor object before closing the 
    // server session.
    delete iSrvMonitor;
    iSrvMonitor = NULL;        

    // Delete the Server session
    RAknAppServiceBase::Close();
    
    // Set the Launch type so that next launchs will succeed
    iLaunchType = ELaunchNone;
    
    // Sets the Launch 
    // Complete the request with KErrCancel
    TRequestStatus*     status = iRequestStatus;
    User::RequestComplete( status, KErrCancel );
    
    return KErrNone;

    }    
    
// ---------------------------------------------------------------------------
// Sets the Active Object used for issuing asynshronous requests
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::SetLaunchAO( CLocLaunchUiAO*&      aLaunchAO )
    {
    iLaunchAO = aLaunchAO; 
    }

// ---------------------------------------------------------------------------
// Inherited from MLocLaunchUiObserver
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::LaunchUiComplete( TInt    aError )
    {
    // When the server exits due to Exit Command it responds with
    // EEikCmdExit. In this case the actual Error Code is KErrNone.
    // This is needed when we have the  following scenario,
    // 1. If the user does a back from the plugin UI instead of exit,
    //    then the client library will have to delete the Server Monitor
    //    object.
    // 2. If the user does a Exit then the scenario will be handled in
    //    HandleServerAppExit.
    if ( EEikCmdExit != aError )
        {
        delete iSrvMonitor;
        iSrvMonitor = NULL;

        // Delete the Server session
        Close();
        }
    else
        {
        // In case the Error value is EEikCmdExit, change it to KErrNone.
        // The session and the Server Monitor object will be taken care of
        // by the HandleServerAppExit() which gets triggered by the Server
        // Exit.
        aError = KErrNone;
        }

    iLaunchType = ELaunchNone;
    TRequestStatus* status = iRequestStatus;
    User::RequestComplete( status, aError );
    }

// ---------------------------------------------------------------------------
// Returns the Service UID of requested service
// ---------------------------------------------------------------------------
//
TUid RLocSettingsUiService::ServiceUid() const
    {
    return TUid::Uid( KLocSettingsUiServiceId );    
    }

// ---------------------------------------------------------------------------
// Receive event about server Exit. Triggered only for Embedded Launch case.
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::HandleServerAppExit(TInt aReason)
    {
    // Delete the Server monitor object.
    delete iSrvMonitor;
    iSrvMonitor = NULL;
    // Delete the Server session
    Close();
    if ( EEikCmdExit == aReason )
        {
        // The base class implementation is a Series60 behaviour. Hence
        // it works only if the Command ID is EAknCmdExit. Whereas from the
        // Server side we exit only for EEikCmdExit. Hence this fix is
        // needed for the correct Exit behaviour for Embedded Launch scenario.
        aReason = EAknCmdExit;
        }
    // Base call the AvKon Implementation.
    MAknServerAppExitObserver::HandleServerAppExit(aReason);
    }


// ---------------------------------------------------------------------------
// Connects to a non embedded server instance.
// ---------------------------------------------------------------------------
//
void RLocSettingsUiService::ConnectServerL()
    {
    TInt retry = KNumofConnectAttempts;
    TInt err = KErrNone;

    for (;;) // Forever
    	{
    	TUid    serviceuid = TUid::Uid( KLocSettingsUiServiceId );
    	TVersion*    version = reinterpret_cast< TVersion* >( &serviceuid );
    	err = CreateSession( KLocSettingsUiServerName, 
    	                     *version,
    	                     KDefaultMessageSlots );
    	if ( err != KErrNotFound && err != KErrServerTerminated )
    		{
    		break;
    		}

    	if ( --retry == 0 )
    		{
    		break;
    		}

    	err = StartServer();

    	if ( err != KErrAlreadyExists && err != KErrNone)
    		{
    		break;
    		}
    	}
    if( KErrNone != err )
        {
        User::Leave( err );
        }
    }
 
// ---------------------------------------------------------------------------
// Starts a new server instance
// ---------------------------------------------------------------------------
//   
TInt RLocSettingsUiService::StartServer()
    {
    const TUidType serverUid(KNullUid, KNullUid, TUid::Uid( KLocSettingsUiServerUid ));

    // Simultaneous launching of two such processes should be detected 
    // when the second one attempts to create the server object, 
    // failing with KErrAlreadyExists.
    //
    RProcess server;
    TInt ret = server.Create( KLocSettingsUiServerExe, KNullDesC, serverUid );

    if (ret != KErrNone)
        {
        return ret;
        }

    TRequestStatus died;
    server.Rendezvous( died );

    if ( died != KRequestPending )
        {
        // logon failed - server is not yet running, so cannot have terminated
        User::WaitForRequest( died );           // eat signal
        server.Kill( 0 );                       // abort startup
        }
    else
        {
        server.Resume();
        User::WaitForRequest( died );           // wait for start or death
        }

    // we can't use the 'exit reason' if the server panicked as this
    // is the panic 'reason' and may be '0' which cannot be distinguished
    // from KErrNone
    ret = ( server.ExitType() == EExitPanic ) ? KErrGeneral : died.Int();
    server.Close();
    return ret;
    }