--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothengine/btnotif/btnotifsrv/src/btnotifserver.cpp Fri May 14 16:01:46 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;
+ }
+
+