bluetoothengine/btserviceutil/src/btdevrepositoryimpl.cpp
branchRCL_3
changeset 56 9386f31cc85b
parent 55 613943a21004
child 61 269724087bed
equal deleted inserted replaced
55:613943a21004 56:9386f31cc85b
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: respository of remote Bluetooth devices.
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btdevrepositoryimpl.h"
       
    19 #include <e32property.h>
       
    20 #include <bt_subscribe.h>
       
    21 #include <btservices/btdevrepository.h>
       
    22 #include "btserviceutilconsts.h"
       
    23 
       
    24 // ---------------------------------------------------------------------------
       
    25 // Tells if two CBTDevice instances are for the same remote device
       
    26 // ---------------------------------------------------------------------------
       
    27 //
       
    28 TBool CompareDeviceByAddress( const CBTDevice& aDevA, const CBTDevice& aDevB )
       
    29     {
       
    30     return aDevA.BDAddr() == aDevB.BDAddr();
       
    31     }
       
    32 
       
    33 // ---------------------------------------------------------------------------
       
    34 // Tells if these two instances are for the same remote device
       
    35 // ---------------------------------------------------------------------------
       
    36 //
       
    37 TBool MatchDeviceAddress(const TBTDevAddr* aAddr, const CBTDevice& aDev)
       
    38     {
       
    39     return *aAddr == aDev.BDAddr();
       
    40     }
       
    41 
       
    42 // ---------------------------------------------------------------------------
       
    43 // Tells if these two instances are for the same remote device
       
    44 // ---------------------------------------------------------------------------
       
    45 //
       
    46 TBool MatchDeviceAddress(const TBTDevAddr* aAddr, const CBtDevExtension& aDev)
       
    47     {
       
    48     return *aAddr == aDev.Device().BDAddr();
       
    49     }
       
    50 
       
    51 // ======== MEMBER FUNCTIONS ========
       
    52 
       
    53 // ---------------------------------------------------------------------------
       
    54 // C++ default constructor
       
    55 // ---------------------------------------------------------------------------
       
    56 //
       
    57 CBtDevRepositoryImpl::CBtDevRepositoryImpl()
       
    58     {
       
    59     }
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // Symbian 2nd-phase constructor
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 void CBtDevRepositoryImpl::ConstructL()
       
    66     {
       
    67     // connect to registry
       
    68     User::LeaveIfError( iBTRegServ.Connect() );
       
    69     User::LeaveIfError( iBTRegistry.Open( iBTRegServ ) );
       
    70     iRegistryActive = CBtSimpleActive::NewL(
       
    71            *this, BtServiceUtil::ECreateRemoteDeviceViewRequest );
       
    72     // Start to get the list of devices from registry.
       
    73     CreateRemoteDeviceView();
       
    74     
       
    75     User::LeaveIfError( iBtRegistryKey.Attach(
       
    76             KPropertyUidBluetoothCategory, 
       
    77             KPropertyKeyBluetoothGetRegistryTableChange ) );
       
    78 
       
    79     iRegistryKeyActive = CBtSimpleActive::NewL( *this, BtServiceUtil::ERegistryPubSubWatcher );
       
    80     iBtRegistryKey.Subscribe( iRegistryKeyActive->RequestStatus() );
       
    81     iRegistryKeyActive->GoActive();
       
    82     iBtengConn = CBTEngConnMan::NewL( this );
       
    83     }
       
    84 
       
    85 // ---------------------------------------------------------------------------
       
    86 // NewL
       
    87 // ---------------------------------------------------------------------------
       
    88 //
       
    89 CBtDevRepositoryImpl* CBtDevRepositoryImpl::NewL()
       
    90     {
       
    91     CBtDevRepositoryImpl* self = NULL;
       
    92     self = new (ELeave) CBtDevRepositoryImpl();
       
    93     CleanupStack::PushL( self );
       
    94     self->ConstructL();
       
    95     CleanupStack::Pop( self );
       
    96     return self;
       
    97     }
       
    98 
       
    99 // ---------------------------------------------------------------------------
       
   100 // Destructor
       
   101 // ---------------------------------------------------------------------------
       
   102 //
       
   103 CBtDevRepositoryImpl::~CBtDevRepositoryImpl()
       
   104     {
       
   105     iObservers.Close();
       
   106     delete iBtengConn;
       
   107     delete iRegistryActive;
       
   108     delete iRegRespRemoteDevices;
       
   109     iDevices.ResetAndDestroy();
       
   110     iDevices.Close();
       
   111     iBTRegistry.Close();
       
   112     iBTRegServ.Close();
       
   113     delete iRegistryKeyActive;
       
   114     iBtRegistryKey.Close();
       
   115     }
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 // AddObserverL
       
   119 // ---------------------------------------------------------------------------
       
   120 //
       
   121 void CBtDevRepositoryImpl::AddObserverL( MBtDevRepositoryObserver* aObserver )
       
   122     {
       
   123     // Do not allow null pointer.
       
   124     if ( aObserver )
       
   125         {
       
   126         iObservers.AppendL( aObserver );
       
   127         }
       
   128     }
       
   129 
       
   130 // ---------------------------------------------------------------------------
       
   131 // RemoveObserver
       
   132 // ---------------------------------------------------------------------------
       
   133 //
       
   134 void CBtDevRepositoryImpl::RemoveObserver( MBtDevRepositoryObserver* aObserver )
       
   135     {
       
   136     TInt i = iObservers.Find( aObserver );
       
   137     if ( i >= 0 )
       
   138         {
       
   139         iObservers.Remove( i );
       
   140         }
       
   141     }
       
   142 
       
   143 // ---------------------------------------------------------------------------
       
   144 // IsInitialized
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 TBool CBtDevRepositoryImpl::IsInitialized() const
       
   148     {
       
   149     return iInitialized;
       
   150     }
       
   151 
       
   152 // ---------------------------------------------------------------------------
       
   153 // AllDevices
       
   154 // ---------------------------------------------------------------------------
       
   155 //
       
   156 const RDevExtensionArray& CBtDevRepositoryImpl::AllDevices() const
       
   157     {
       
   158     return iDevices;
       
   159     }
       
   160 
       
   161 // ---------------------------------------------------------------------------
       
   162 // Device
       
   163 // ---------------------------------------------------------------------------
       
   164 //
       
   165 const CBtDevExtension* CBtDevRepositoryImpl::Device( 
       
   166         const TBTDevAddr& aAddr ) const
       
   167     {
       
   168     TInt pos = iDevices.Find( aAddr, MatchDeviceAddress);
       
   169     if ( pos > -1 )
       
   170         {
       
   171         return iDevices[pos];
       
   172         }
       
   173     return NULL;
       
   174     }
       
   175 
       
   176 // ---------------------------------------------------------------------------
       
   177 // ReInitialize
       
   178 // ---------------------------------------------------------------------------
       
   179 //
       
   180 void CBtDevRepositoryImpl::ReInitialize()
       
   181     {
       
   182     iInitialized = EFalse;
       
   183     if ( !iRegistryActive->IsActive() )
       
   184         {
       
   185         CreateRemoteDeviceView();
       
   186         }
       
   187     else
       
   188         {
       
   189         // This counter-increasing
       
   190         // will force to re-create a registry view later.
       
   191         ++iNotHandledRegEventCounter;
       
   192         }
       
   193     }
       
   194 
       
   195 // ---------------------------------------------------------------------------
       
   196 // From class MBtSimpleActiveObserver.
       
   197 // Checks if there is an authentication result.
       
   198 // ---------------------------------------------------------------------------
       
   199 //
       
   200 void CBtDevRepositoryImpl::RequestCompletedL( CBtSimpleActive* aActive, TInt aStatus )
       
   201     {
       
   202     if ( aActive->RequestId() == BtServiceUtil::ECreateRemoteDeviceViewRequest )
       
   203         {
       
   204         HandleCreateRemoteDeviceViewCompletedL( aStatus );
       
   205         }
       
   206     else if ( aActive->RequestId() == BtServiceUtil::EGetRemoteDevicesRequest )
       
   207         {
       
   208         HandleGetRemoteDevicesCompletedL( aStatus );
       
   209         }
       
   210     else if ( aActive->RequestId() == BtServiceUtil::ERegistryPubSubWatcher )
       
   211         {
       
   212         TInt myChangedTable;
       
   213         iBtRegistryKey.Subscribe( aActive->RequestStatus() );
       
   214         aActive->GoActive();
       
   215         TInt err = iBtRegistryKey.Get( myChangedTable );
       
   216         if( !err && myChangedTable == KRegistryChangeRemoteTable )
       
   217             {
       
   218             if ( !iRegistryActive->IsActive() )
       
   219                 {
       
   220                 CreateRemoteDeviceView();
       
   221                 }
       
   222             else
       
   223                 {
       
   224                 iNotHandledRegEventCounter++;
       
   225                 }
       
   226             }
       
   227         }
       
   228     }
       
   229 
       
   230 // ---------------------------------------------------------------------------
       
   231 // From class MBtSimpleActiveObserver.
       
   232 // Checks if there is an authentication result.
       
   233 // ---------------------------------------------------------------------------
       
   234 //
       
   235 void CBtDevRepositoryImpl::CancelRequest( TInt aRequestId )
       
   236     {
       
   237     if ( aRequestId == BtServiceUtil::ECreateRemoteDeviceViewRequest )
       
   238         {
       
   239         iBTRegistry.CancelRequest(iRegistryActive->RequestStatus());
       
   240         }
       
   241     else if ( aRequestId == BtServiceUtil::EGetRemoteDevicesRequest )
       
   242         {
       
   243         iRegRespRemoteDevices->Cancel();
       
   244         }
       
   245     else if ( aRequestId == BtServiceUtil::ERegistryPubSubWatcher )
       
   246         {
       
   247         iBtRegistryKey.Cancel();
       
   248         }
       
   249     }
       
   250 
       
   251 // ---------------------------------------------------------------------------
       
   252 // From class MBtSimpleActiveObserver.
       
   253 // ---------------------------------------------------------------------------
       
   254 //
       
   255 void CBtDevRepositoryImpl::HandleError( CBtSimpleActive* aActive, TInt aError )
       
   256     {
       
   257     (void) aError;
       
   258     if ( aActive->RequestId() == BtServiceUtil::ECreateRemoteDeviceViewRequest || 
       
   259             aActive->RequestId() == BtServiceUtil::EGetRemoteDevicesRequest )
       
   260         {// leave happened in registry operation, delete registry response:
       
   261         delete iRegRespRemoteDevices;
       
   262         iRegRespRemoteDevices = NULL;
       
   263         }
       
   264     }
       
   265 
       
   266 // ---------------------------------------------------------------------------
       
   267 // From class MBTEngConnObserver.
       
   268 // ---------------------------------------------------------------------------
       
   269 //
       
   270 void CBtDevRepositoryImpl::ConnectComplete( TBTDevAddr& aAddr, TInt aErr, 
       
   271                                RBTDevAddrArray* aConflicts)
       
   272     {
       
   273     // connection is single profile based, to make sure getting the correct status, 
       
   274     // we always retrieve it from btengconnman:
       
   275     (void)aConflicts;
       
   276     (void) aErr;
       
   277     TInt pos = iDevices.Find( aAddr, MatchDeviceAddress );
       
   278     if ( pos > -1 )
       
   279         {
       
   280         TBTEngConnectionStatus old = iDevices[pos]->ServiceConnectionStatus();
       
   281         TBTEngConnectionStatus  status = EBTEngNotConnected;
       
   282         // error returned from the call is treated as not connected.
       
   283         (void) iBtengConn->IsConnected( aAddr,  status );
       
   284         iDevices[pos]->SetServiceConnectionStatus( status );
       
   285         
       
   286         if ( old != status &&
       
   287              ( status == EBTEngConnected ||
       
   288                status == EBTEngNotConnected ) )
       
   289             {
       
   290             for ( TInt i = 0; i < iObservers.Count(); ++i )
       
   291                 {
       
   292                 iObservers[i]->ServiceConnectionChanged( 
       
   293                         *(iDevices[pos]), status == EBTEngConnected );
       
   294                 }
       
   295             }
       
   296         }
       
   297     }
       
   298 
       
   299 // ---------------------------------------------------------------------------
       
   300 // From class MBTEngConnObserver.
       
   301 // ---------------------------------------------------------------------------
       
   302 //
       
   303 void CBtDevRepositoryImpl::DisconnectComplete( TBTDevAddr& aAddr, TInt aErr )
       
   304     {
       
   305     // unified handling for connections status events:
       
   306     ConnectComplete( aAddr, aErr, NULL);
       
   307     }
       
   308 
       
   309 // ---------------------------------------------------------------------------
       
   310 // issue creating a remote device view from the registry
       
   311 // ---------------------------------------------------------------------------
       
   312 //
       
   313 void CBtDevRepositoryImpl::CreateRemoteDeviceView()
       
   314     {
       
   315     iNotHandledRegEventCounter = 0;
       
   316     (void) iBTRegistry.CloseView();
       
   317     TBTRegistrySearch searchPattern;
       
   318     searchPattern.FindAll();
       
   319     iRegistryActive->SetRequestId( BtServiceUtil::ECreateRemoteDeviceViewRequest );
       
   320     iBTRegistry.CreateView( searchPattern, iRegistryActive->iStatus );
       
   321     iRegistryActive->GoActive();
       
   322     }
       
   323 
       
   324 // ---------------------------------------------------------------------------
       
   325 // gets the paired devices from the view created by CreatePairedDevicesView
       
   326 // ---------------------------------------------------------------------------
       
   327 //
       
   328 void CBtDevRepositoryImpl::GetRemoteDevicesL()
       
   329     {
       
   330     delete iRegRespRemoteDevices;
       
   331     iRegRespRemoteDevices = NULL;
       
   332     iRegRespRemoteDevices = CBTRegistryResponse::NewL( iBTRegistry );
       
   333     iRegistryActive->SetRequestId( BtServiceUtil::EGetRemoteDevicesRequest );
       
   334     iRegRespRemoteDevices->Start( iRegistryActive->iStatus );
       
   335     iRegistryActive->GoActive();
       
   336     }
       
   337 
       
   338 // ---------------------------------------------------------------------------
       
   339 // re-create a paired device view if registry was changed during the previous
       
   340 // operation. otherwise if the view is not empty, get the remote devices.
       
   341 // ---------------------------------------------------------------------------
       
   342 //
       
   343 void CBtDevRepositoryImpl::HandleCreateRemoteDeviceViewCompletedL( TInt aStatus )
       
   344     {
       
   345     // aStatus may indicate the number of devices from registry.
       
   346     // However, our algorithm does not rely on this return error 
       
   347     // for implementation simplicity.
       
   348     (void) aStatus;
       
   349     if (iNotHandledRegEventCounter)
       
   350         { // more registry change detected, create paired device view again:
       
   351         CreateRemoteDeviceView( );
       
   352         }
       
   353     else
       
   354         {
       
   355         GetRemoteDevicesL( );
       
   356         }
       
   357     }
       
   358 
       
   359 // ---------------------------------------------------------------------------
       
   360 // update remote device list. if registry was changed, create a new view.
       
   361 // otherwise inform client for any changes.
       
   362 // ---------------------------------------------------------------------------
       
   363 //
       
   364 void CBtDevRepositoryImpl::HandleGetRemoteDevicesCompletedL( TInt aStatus )
       
   365     {
       
   366     // aStatus may indicate the number of devices from registry.
       
   367     // However, our algorithm does not rely on this return error.
       
   368     (void) aStatus;
       
   369     if (iNotHandledRegEventCounter)
       
   370         { // more registry change detected, create paired device view again:
       
   371         CreateRemoteDeviceView( );
       
   372         return;
       
   373         }
       
   374 
       
   375     UpdateRemoteDeviceRepositoryL();
       
   376     if ( !iInitialized )
       
   377         {
       
   378         iInitialized = ETrue;
       
   379         // The first time we have got the device lists from registry,
       
   380         // Get the connections statuses of these devices from bteng.
       
   381         for ( TInt i = iDevices.Count() - 1; i > -1; --i )
       
   382             {
       
   383             TBTEngConnectionStatus  status = EBTEngNotConnected;
       
   384             // error returned from the call is treated as not connected.
       
   385             (void) iBtengConn->IsConnected( iDevices[i]->Addr(),  status );
       
   386             iDevices[i]->SetServiceConnectionStatus( status );
       
   387             }
       
   388         for ( TInt i = 0; i < iObservers.Count(); ++i )
       
   389             {
       
   390             iObservers[i]->RepositoryInitialized();
       
   391             }
       
   392         }
       
   393     }
       
   394 
       
   395 // ---------------------------------------------------------------------------
       
   396 // update remote devices in local array with the latest data
       
   397 // ---------------------------------------------------------------------------
       
   398 //
       
   399 void CBtDevRepositoryImpl::UpdateRemoteDeviceRepositoryL()
       
   400     {
       
   401     TIdentityRelation<CBTDevice> addrComp( CompareDeviceByAddress );
       
   402     RBTDeviceArray& devsFromReg = iRegRespRemoteDevices->Results();
       
   403     for ( TInt i = iDevices.Count() - 1; i > -1; --i )
       
   404         {
       
   405         TInt pos = devsFromReg.Find( &(iDevices[i]->Device()), addrComp );
       
   406         if ( pos > KErrNotFound )
       
   407             {
       
   408             // Device is found in registry, check if its properties have been changed
       
   409             TUint similarity = devsFromReg[pos]->CompareTo( iDevices[i]->Device() );
       
   410             TBool changed = EFalse;
       
   411             if ( similarity != 
       
   412                     ( CBTDevice::EAllNameProperties | 
       
   413                       TBTNamelessDevice::EAllNamelessProperties) )
       
   414                 {
       
   415                 // This device was updated in registry.
       
   416                 // move its ownership to local store
       
   417                 iDevices[i]->SetDeviceL( devsFromReg[pos] );
       
   418                 changed = ETrue;
       
   419                 }
       
   420             else
       
   421                 {
       
   422                 // This device has no update:
       
   423                 delete devsFromReg[pos];
       
   424                 }
       
   425             // either the instance at pos has been moved or deleted.
       
   426             devsFromReg.Remove( pos );
       
   427             if ( iInitialized && changed )
       
   428                 {
       
   429                 for ( TInt counter = 0; counter < iObservers.Count(); ++counter )
       
   430                     {
       
   431                     iObservers[counter]->ChangedInRegistry( *iDevices[i], similarity );
       
   432                     }
       
   433                 }
       
   434             }
       
   435         else
       
   436             {
       
   437             // This device was deleted from registry.
       
   438             // Free it from the local store before informing client.
       
   439             TBTDevAddr addr = iDevices[i]->Addr();
       
   440             delete iDevices[i];
       
   441             iDevices.Remove( i );
       
   442             if ( iInitialized )
       
   443                 {
       
   444                 for ( TInt counter = 0; counter < iObservers.Count(); ++counter )
       
   445                     {
       
   446                     iObservers[counter]->DeletedFromRegistry( addr );
       
   447                     }
       
   448                 }
       
   449             }
       
   450         }
       
   451     
       
   452     // Remaining devices in iRegRespRemoteDevices are new devices:
       
   453     for ( TInt i = devsFromReg.Count()- 1; i > -1 ; --i )
       
   454         {
       
   455         CBtDevExtension* devExt = CBtDevExtension::NewLC( devsFromReg[i] );
       
   456         iDevices.AppendL( devExt );
       
   457         CleanupStack::Pop( devExt );
       
   458         devsFromReg.Remove( i );
       
   459         if ( iInitialized )
       
   460             {
       
   461             for ( TInt counter = 0; counter < iObservers.Count(); ++counter )
       
   462                 {
       
   463                 iObservers[counter]->AddedToRegistry( *devExt );
       
   464                 }
       
   465             }
       
   466         }
       
   467     // the devices in devsFromReg was either deleted, or moved.
       
   468     delete iRegRespRemoteDevices;
       
   469     iRegRespRemoteDevices = NULL;
       
   470     }