diff -r f05641c183ff -r 43824b19ee35 bluetoothengine/btserviceutil/src/btdevrepositoryimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetoothengine/btserviceutil/src/btdevrepositoryimpl.cpp Fri May 14 16:01:46 2010 +0300 @@ -0,0 +1,439 @@ +/* +* Copyright (c) 2010 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: respository of remote Bluetooth devices. +* +*/ + +#include "btdevrepositoryimpl.h" +#include +#include +#include +#include "btserviceutilconsts.h" + +// --------------------------------------------------------------------------- +// Tells if two CBTDevice instances are for the same remote device +// --------------------------------------------------------------------------- +// +TBool CompareDeviceByAddress( const CBTDevice& aDevA, const CBTDevice& aDevB ) + { + return aDevA.BDAddr() == aDevB.BDAddr(); + } + +// --------------------------------------------------------------------------- +// Tells if these two instances are for the same remote device +// --------------------------------------------------------------------------- +// +TBool MatchDeviceAddress(const TBTDevAddr* aAddr, const CBTDevice& aDev) + { + return *aAddr == aDev.BDAddr(); + } + +// --------------------------------------------------------------------------- +// Tells if these two instances are for the same remote device +// --------------------------------------------------------------------------- +// +TBool MatchDeviceAddress(const TBTDevAddr* aAddr, const CBtDevExtension& aDev) + { + return *aAddr == aDev.Device().BDAddr(); + } + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// C++ default constructor +// --------------------------------------------------------------------------- +// +CBtDevRepositoryImpl::CBtDevRepositoryImpl() + { + } + +// --------------------------------------------------------------------------- +// Symbian 2nd-phase constructor +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::ConstructL() + { + // connect to registry + User::LeaveIfError( iBTRegServ.Connect() ); + User::LeaveIfError( iBTRegistry.Open( iBTRegServ ) ); + iRegistryActive = CBtSimpleActive::NewL( + *this, BtServiceUtil::ECreateRemoteDeviceViewRequest ); + // Start to get the list of devices from registry. + CreateRemoteDeviceView(); + + User::LeaveIfError( iBtRegistryKey.Attach( + KPropertyUidBluetoothCategory, + KPropertyKeyBluetoothGetRegistryTableChange ) ); + + iRegistryKeyActive = CBtSimpleActive::NewL( *this, BtServiceUtil::ERegistryPubSubWatcher ); + iBtRegistryKey.Subscribe( iRegistryKeyActive->RequestStatus() ); + iRegistryKeyActive->GoActive(); + iBtengConn = CBTEngConnMan::NewL( this ); + } + +// --------------------------------------------------------------------------- +// NewL +// --------------------------------------------------------------------------- +// +CBtDevRepositoryImpl* CBtDevRepositoryImpl::NewL() + { + CBtDevRepositoryImpl* self = NULL; + self = new (ELeave) CBtDevRepositoryImpl(); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CBtDevRepositoryImpl::~CBtDevRepositoryImpl() + { + iObservers.Close(); + delete iBtengConn; + delete iRegistryActive; + delete iRegRespRemoteDevices; + iDevices.ResetAndDestroy(); + iDevices.Close(); + iBTRegistry.Close(); + iBTRegServ.Close(); + delete iRegistryKeyActive; + iBtRegistryKey.Close(); + } + +// --------------------------------------------------------------------------- +// AddObserverL +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::AddObserverL( MBtDevRepositoryObserver* aObserver ) + { + // Do not allow null pointer. + if ( aObserver ) + { + iObservers.AppendL( aObserver ); + } + } + +// --------------------------------------------------------------------------- +// RemoveObserver +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::RemoveObserver( MBtDevRepositoryObserver* aObserver ) + { + TInt i = iObservers.Find( aObserver ); + if ( i >= 0 ) + { + iObservers.Remove( i ); + } + } + +// --------------------------------------------------------------------------- +// IsInitialized +// --------------------------------------------------------------------------- +// +TBool CBtDevRepositoryImpl::IsInitialized() const + { + return iInitialized; + } + +// --------------------------------------------------------------------------- +// AllDevices +// --------------------------------------------------------------------------- +// +const RDevExtensionArray& CBtDevRepositoryImpl::AllDevices() const + { + return iDevices; + } + +// --------------------------------------------------------------------------- +// Device +// --------------------------------------------------------------------------- +// +const CBtDevExtension* CBtDevRepositoryImpl::Device( + const TBTDevAddr& aAddr ) const + { + TInt pos = iDevices.Find( aAddr, MatchDeviceAddress); + if ( pos > -1 ) + { + return iDevices[pos]; + } + return NULL; + } + +// --------------------------------------------------------------------------- +// From class MBtSimpleActiveObserver. +// Checks if there is an authentication result. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::RequestCompletedL( CBtSimpleActive* aActive, TInt aStatus ) + { + if ( aActive->RequestId() == BtServiceUtil::ECreateRemoteDeviceViewRequest ) + { + HandleCreateRemoteDeviceViewCompletedL( aStatus ); + } + else if ( aActive->RequestId() == BtServiceUtil::EGetRemoteDevicesRequest ) + { + HandleGetRemoteDevicesCompletedL( aStatus ); + } + else if ( aActive->RequestId() == BtServiceUtil::ERegistryPubSubWatcher ) + { + TInt myChangedTable; + iBtRegistryKey.Subscribe( aActive->RequestStatus() ); + aActive->GoActive(); + TInt err = iBtRegistryKey.Get( myChangedTable ); + if( !err && myChangedTable == KRegistryChangeRemoteTable ) + { + if ( !iRegistryActive->IsActive() ) + { + CreateRemoteDeviceView(); + } + else + { + iNotHandledRegEventCounter++; + } + } + } + } + +// --------------------------------------------------------------------------- +// From class MBtSimpleActiveObserver. +// Checks if there is an authentication result. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::CancelRequest( TInt aRequestId ) + { + if ( aRequestId == BtServiceUtil::ECreateRemoteDeviceViewRequest ) + { + iBTRegistry.CancelRequest(iRegistryActive->RequestStatus()); + } + else if ( aRequestId == BtServiceUtil::EGetRemoteDevicesRequest ) + { + iRegRespRemoteDevices->Cancel(); + } + else if ( aRequestId == BtServiceUtil::ERegistryPubSubWatcher ) + { + iBtRegistryKey.Cancel(); + } + } + +// --------------------------------------------------------------------------- +// From class MBtSimpleActiveObserver. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::HandleError( CBtSimpleActive* aActive, TInt aError ) + { + (void) aError; + if ( aActive->RequestId() == BtServiceUtil::ECreateRemoteDeviceViewRequest || + aActive->RequestId() == BtServiceUtil::EGetRemoteDevicesRequest ) + {// leave happened in registry operation, delete registry response: + delete iRegRespRemoteDevices; + iRegRespRemoteDevices = NULL; + } + } + +// --------------------------------------------------------------------------- +// From class MBTEngConnObserver. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::ConnectComplete( TBTDevAddr& aAddr, TInt aErr, + RBTDevAddrArray* aConflicts) + { + // connection is single profile based, to make sure getting the correct status, + // we always retrieve it from btengconnman: + (void)aConflicts; + (void) aErr; + TInt pos = iDevices.Find( aAddr, MatchDeviceAddress ); + if ( pos > -1 ) + { + TBTEngConnectionStatus status = EBTEngNotConnected; + // error returned from the call is treated as not connected. + (void) iBtengConn->IsConnected( aAddr, status ); + iDevices[pos]->SetServiceConnectionStatus( status ); + } + } + +// --------------------------------------------------------------------------- +// From class MBTEngConnObserver. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::DisconnectComplete( TBTDevAddr& aAddr, TInt aErr ) + { + // unified handling for connections status events: + ConnectComplete( aAddr, aErr, NULL); + } + +// --------------------------------------------------------------------------- +// issue creating a remote device view from the registry +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::CreateRemoteDeviceView() + { + iNotHandledRegEventCounter = 0; + (void) iBTRegistry.CloseView(); + TBTRegistrySearch searchPattern; + searchPattern.FindAll(); + iRegistryActive->SetRequestId( BtServiceUtil::ECreateRemoteDeviceViewRequest ); + iBTRegistry.CreateView( searchPattern, iRegistryActive->iStatus ); + iRegistryActive->GoActive(); + } + +// --------------------------------------------------------------------------- +// gets the paired devices from the view created by CreatePairedDevicesView +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::GetRemoteDevicesL() + { + delete iRegRespRemoteDevices; + iRegRespRemoteDevices = NULL; + iRegRespRemoteDevices = CBTRegistryResponse::NewL( iBTRegistry ); + iRegistryActive->SetRequestId( BtServiceUtil::EGetRemoteDevicesRequest ); + iRegRespRemoteDevices->Start( iRegistryActive->iStatus ); + iRegistryActive->GoActive(); + } + +// --------------------------------------------------------------------------- +// re-create a paired device view if registry was changed during the previous +// operation. otherwise if the view is not empty, get the remote devices. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::HandleCreateRemoteDeviceViewCompletedL( TInt aStatus ) + { + // aStatus may indicate the number of devices from registry. + // However, our algorithm does not rely on this return error + // for implementation simplicity. + (void) aStatus; + if (iNotHandledRegEventCounter) + { // more registry change detected, create paired device view again: + CreateRemoteDeviceView( ); + } + else + { + GetRemoteDevicesL( ); + } + } + +// --------------------------------------------------------------------------- +// update remote device list. if registry was changed, create a new view. +// otherwise inform client for any changes. +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::HandleGetRemoteDevicesCompletedL( TInt aStatus ) + { + // aStatus may indicate the number of devices from registry. + // However, our algorithm does not rely on this return error. + (void) aStatus; + if (iNotHandledRegEventCounter) + { // more registry change detected, create paired device view again: + CreateRemoteDeviceView( ); + return; + } + + UpdateRemoteDeviceRepositoryL(); + if ( !iInitialized ) + { + iInitialized = ETrue; + // The first time we have got the device lists from registry, + // Get the connections statuses of these devices from bteng. + for ( TInt i = iDevices.Count() - 1; i > -1; --i ) + { + TBTEngConnectionStatus status = EBTEngNotConnected; + // error returned from the call is treated as not connected. + (void) iBtengConn->IsConnected( iDevices[i]->Addr(), status ); + iDevices[i]->SetServiceConnectionStatus( status ); + } + for ( TInt i = 0; i < iObservers.Count(); ++i ) + { + iObservers[i]->RepositoryInitialiazed(); + } + } + } + +// --------------------------------------------------------------------------- +// update remote devices in local array with the latest data +// --------------------------------------------------------------------------- +// +void CBtDevRepositoryImpl::UpdateRemoteDeviceRepositoryL() + { + TIdentityRelation addrComp( CompareDeviceByAddress ); + RBTDeviceArray& devsFromReg = iRegRespRemoteDevices->Results(); + for ( TInt i = iDevices.Count() - 1; i > -1; --i ) + { + TInt pos = devsFromReg.Find( &(iDevices[i]->Device()), addrComp ); + if ( pos > KErrNotFound ) + { + // Device is found in registry, check if its properties have been changed + TUint similarity = devsFromReg[pos]->CompareTo( iDevices[i]->Device() ); + TBool changed = EFalse; + if ( similarity != + ( CBTDevice::EAllNameProperties | + TBTNamelessDevice::EAllNamelessProperties) ) + { + // This device was updated in registry. + // move its ownership to local store + iDevices[i]->SetDeviceL( devsFromReg[pos] ); + changed = ETrue; + } + else + { + // This device has no update: + delete devsFromReg[pos]; + } + // either the instance at pos has been moved or deleted. + devsFromReg.Remove( pos ); + if ( iInitialized && changed ) + { + for ( TInt i = 0; i < iObservers.Count(); ++i ) + { + iObservers[i]->BtDeviceChangedInRegistry( *iDevices[i], similarity ); + } + } + } + else + { + // This device was deleted from registry. + // Free it from the local store before informing client. + TBTDevAddr addr = iDevices[i]->Addr(); + delete iDevices[i]; + iDevices.Remove( i ); + if ( iInitialized ) + { + for ( TInt i = 0; i < iObservers.Count(); ++i ) + { + iObservers[i]->BtDeviceDeleted( addr ); + } + } + } + } + + // Remaining devices in iRegRespRemoteDevices are new devices: + for ( TInt i = 0; i < devsFromReg.Count() ; i++ ) + { + CBtDevExtension* devExt = CBtDevExtension::NewLC( devsFromReg[i] ); + iDevices.AppendL( devExt ); + CleanupStack::Pop( devExt ); + devsFromReg.Remove( i ); + if ( iInitialized ) + { + for ( TInt i = 0; i < iObservers.Count(); ++i ) + { + iObservers[i]->BtDeviceAdded( *iDevices[ iDevices.Count() - 1 ] ); + } + } + } + // the devices in devsFromReg was either deleted, or moved. + delete iRegRespRemoteDevices; + iRegRespRemoteDevices = NULL; + }