bluetoothengine/btserviceutil/src/btdevrepositoryimpl.cpp
changeset 19 43824b19ee35
child 31 a0ea99b6fa53
--- /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 <e32property.h>
+#include <bt_subscribe.h>
+#include <btservices/btdevrepository.h>
+#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<CBTDevice> 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;
+    }