bluetoothengine/btnotif/btnotifsrv/src/btnotifserver.cpp
changeset 29 48ae3789ce00
child 31 a0ea99b6fa53
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btnotif/btnotifsrv/src/btnotifserver.cpp	Mon May 03 14:36:07 2010 +0300
@@ -0,0 +1,370 @@
+/*
+* ============================================================================
+*  Name        : btnotifserver.cpp
+*  Part of     : bluetoothengine / btnotif
+*  Description : Server class for handling commands from clients, and the 
+*                central class in btnotif thread.
+*
+*  Copyright © 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:
+*  Nokia Corporation
+* ============================================================================
+* Template version: 4.1
+*/
+
+#include "btnotifserver.h"
+#include <btservices/btdevrepository.h>
+#include "btnotifsession.h"
+#include "btnotifconnectiontracker.h"
+#include "btnotifsettingstracker.h"
+#include "btnotificationmanager.h"
+#include "btnotifdeviceselector.h"
+#include "btnotifserversecpolicy.h"
+#include "btnotifclientserver.h"
+
+/**  Panic category */
+_LIT( KBTNotifPanic, "BTNotif panic" );
+
+/**  Timeout (10 sec) for shutting down the server 
+ * (when BT power is off and no clients connected). */
+const TInt KBTNtoifShutdownTimeout = 10 * 1000 * 1000;
+
+// ======== LOCAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Start the server.
+// ---------------------------------------------------------------------------
+//
+static void RunServerL()
+    {
+    BOstraceFunctionEntry0( DUMMY_DEVLIST );
+    
+    (void) User::RenameThread( KBTNotifServerName );
+    // Create and install the active scheduler for this thread.
+    CActiveScheduler* scheduler = new( ELeave ) CActiveScheduler();
+    CleanupStack::PushL( scheduler );
+    CActiveScheduler::Install( scheduler );
+    // create the server (and leave it on the cleanup stack)
+    CBTNotifServer* notifServer = CBTNotifServer::NewLC();
+    // Initialisation complete, now signal the client
+    RProcess::Rendezvous( KErrNone );
+        // The server is now up and running.
+    BOstrace0( TRACE_NORMAL, DUMMY_DEVLIST, "[BTNOTIF]\t BTNotif server now up and running" );
+    // The active scheduler runs during the lifetime of this thread.
+    CActiveScheduler::Start();
+    // Stopping the active scheduler means terminating the thread.
+    // Cleanup the server and scheduler.
+    CleanupStack::PopAndDestroy( notifServer );
+    CleanupStack::PopAndDestroy( scheduler );
+    BOstraceFunctionExit0( DUMMY_DEVLIST );
+    }
+
+// ---------------------------------------------------------------------------
+// Panic the server.
+// ---------------------------------------------------------------------------
+//
+void PanicServer( TInt aReason )
+    {
+    User::Panic( KBTNotifPanic, aReason );
+    }
+
+// ---------------------------------------------------------------------------
+// Panic the client through the client-side message.
+// ---------------------------------------------------------------------------
+//
+void PanicClient( const RMessage2& aMessage, TInt aReason )
+    {
+    aMessage.Panic( KBTNotifPanic, aReason );
+    }
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CBTNotifServer::CBTNotifServer()
+:   CPolicyServer( EPriorityUserInput, KBTNotifServerPolicy )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTNotifServer::ConstructL()
+    {
+    // Add the server to the active scheduler (from CServer2):
+    StartL( KBTNotifServerName );
+    iAsyncCb = new( ELeave ) CAsyncCallBack( EPriorityHigh );
+    TCallBack cb( AsyncConstructCb, this );
+    iAsyncCb->Set( cb );
+    iAsyncCb->CallBack();
+    }
+
+// ---------------------------------------------------------------------------
+// Asynchronous 3rd-phase constructor
+// ---------------------------------------------------------------------------
+//
+void CBTNotifServer::AsyncConstructL()
+    {
+    iSettingsTracker = CBTNotifSettingsTracker::NewL( this );
+    if( iSettingsTracker->GetPowerState() == EBTPowerOn )
+        {
+        iConnectionTracker = CBTNotifConnectionTracker::NewL( this );
+        }
+    iNotificationMgr = CBTNotificationManager::NewL( this );
+    
+    iTimer = CDeltaTimer::NewL(CActive::EPriorityLow);
+    TCallBack shutdownCb( ShutdownTimeout, this );
+    iShutdownTimerEntry.Set( shutdownCb );
+    // The server class does not handle any registry events.
+    // Classes that want to receive these events must register
+    // via observer interface.
+    iDevRep = CBtDevRepository::NewL();
+    }
+
+// ---------------------------------------------------------------------------
+// Callback for asynchronous construction.
+// ---------------------------------------------------------------------------
+//
+TInt CBTNotifServer::AsyncConstructCb( TAny* aPtr )
+    {
+    TRAPD( err, ( (CBTNotifServer*) aPtr )->AsyncConstructL() );
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// NewLC.
+// ---------------------------------------------------------------------------
+//
+CBTNotifServer* CBTNotifServer::NewLC()
+    {
+    CBTNotifServer* self = new( ELeave ) CBTNotifServer();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CBTNotifServer::~CBTNotifServer()
+    {
+    delete iDevSelector;
+    delete iSettingsTracker;
+    delete iConnectionTracker;
+    delete iNotificationMgr;
+    delete iAsyncCb;
+    delete iTimer;
+    delete iDevRep;
+    }
+
+// ---------------------------------------------------------------------------
+// Handle a change in BT power state.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifServer::HandlePowerStateChangeL( TBTPowerStateValue aState )
+    {
+    if( aState && !iConnectionTracker )
+        {
+        // only construct tracker if it is not available yet
+        iConnectionTracker = CBTNotifConnectionTracker::NewL( this );
+        }
+    else
+        {
+        delete iConnectionTracker;
+        iConnectionTracker = NULL;
+        }
+    CheckIdle( aState );
+    }
+
+// ---------------------------------------------------------------------------
+// Increase the session count.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifServer::AddSession()
+    {
+    ++iSessionCount;
+    iTimer->Remove( iShutdownTimerEntry );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Decrease the session count.
+// ---------------------------------------------------------------------------
+//
+void CBTNotifServer::RemoveSession()
+    {
+    if ( iSessionCount > 0 )
+        {
+        // session counter can't be less than 0
+        --iSessionCount;
+        }
+    CheckIdle( iSettingsTracker->GetPowerState() );
+    }
+
+// ---------------------------------------------------------------------------
+// get the singleton instance of device repository
+// ---------------------------------------------------------------------------
+//
+CBtDevRepository& CBTNotifServer::DevRepository()
+    {
+    return *iDevRep;
+    }
+
+// ---------------------------------------------------------------------------
+// get the singleton instance of device search notifier
+// ---------------------------------------------------------------------------
+//
+CBTNotifDeviceSelector& CBTNotifServer::DeviceSelectorL()
+    {
+    if ( ! iDevSelector )
+        {
+        iDevSelector = CBTNotifDeviceSelector::NewL( *this );
+        }
+    return *iDevSelector;
+    }
+
+// ---------------------------------------------------------------------------
+// Searches for a client message from a message handle and completes it.
+// ---------------------------------------------------------------------------
+//
+TInt CBTNotifServer::CompleteMessage( TInt aHandle, TInt aReason, const TDesC8& aReply )
+    {
+    TInt err = KErrNotFound;
+    iSessionIter.SetToFirst();
+    CBTNotifSession* session = NULL;
+    while( ( session = (CBTNotifSession*) iSessionIter++ ) != NULL )
+        {
+        err = session->CompleteMessage( aHandle, aReason, aReply );
+        if( err != KErrNotFound )
+            {
+            // Found the correct session, and message, and completed it.
+            break;
+            }
+        }
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Searches for a client message from a message handle and returns it.
+// ---------------------------------------------------------------------------
+//
+const RMessage2* CBTNotifServer::FindMessageFromHandle( TInt aHandle )
+    {
+    const RMessage2* message = NULL;
+    iSessionIter.SetToFirst();
+    CBTNotifSession* session = NULL;
+    while( ( session = (CBTNotifSession*) iSessionIter++ ) != NULL )
+        {
+        message = session->FindMessageFromHandle( aHandle );
+        if( message )
+            {
+            // Found the correct session and message to return.
+            break;
+            }
+        }
+    return message;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Searches for a client message from a message handle and returns it.
+// ---------------------------------------------------------------------------
+//
+const RMessage2* CBTNotifServer::FindMessageFromUid( TInt aUid )
+    {
+    const RMessage2* message = NULL;
+    iSessionIter.SetToFirst();
+    CBTNotifSession* session = NULL;
+    while( ( session = (CBTNotifSession*) iSessionIter++ ) != NULL )
+        {
+        message = session->FindMessageFromUid( aUid );
+        if( message )
+            {
+            // Found the correct session and message to return.
+            break;
+            }
+        }
+    return message;
+    }
+
+
+// ---------------------------------------------------------------------------
+// From class CPolicyServer.
+// Create a new session object.
+// ---------------------------------------------------------------------------
+//
+CSession2* CBTNotifServer::NewSessionL( const TVersion& aVersion, 
+    const RMessage2& aMessage ) const
+    {
+    (void) aMessage;
+    // Compare our version with client-side version, CServer2 requires that 
+    // we leave if they are not compatible. 
+    TVersion srvVersion( KBTNotifServerVersionMajor, KBTNotifServerVersionMinor, 
+                          KBTNotifServerVersionBuild );
+
+    if( !User::QueryVersionSupported( aVersion, srvVersion ) )
+        {
+        // EFalse is returned if our version is not less than or 
+        // equal to the client version.
+        User::Leave( KErrNotSupported );
+        }
+    return CBTNotifSession::NewL();
+    }
+
+void CBTNotifServer::CheckIdle( TBTPowerStateValue aState )
+    {
+    // In special scenarios, we do not have to remove the timer and queue it 
+    // again, but these scenarios rarely happen in end-user use cases. 
+    iTimer->Remove( iShutdownTimerEntry );
+    if ( iSessionCount == 0 && aState == EBTPowerOff )
+        {
+        // BT power is off, start the shutdown timer.
+        TTimeIntervalMicroSeconds32 interval = KBTNtoifShutdownTimeout;
+        iTimer->Queue( interval, iShutdownTimerEntry );
+        }
+    }
+
+TInt CBTNotifServer::ShutdownTimeout( TAny* aPtr )
+    {
+    (void) aPtr;
+    CActiveScheduler::Stop();
+    return KErrNone;    
+    }
+
+// ======== GLOBAL FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// Main function of the executable.
+// ---------------------------------------------------------------------------
+//
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+    CTrapCleanup* cleanup = CTrapCleanup::New();
+    TInt err = KErrNoMemory;
+    if ( cleanup )
+        {
+        TRAP( err, RunServerL() );
+        delete cleanup;
+        }
+    __UHEAP_MARKEND;
+    return err;
+    }
+
+