bluetooth/btstack/linkmgr/pairingscache.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "pairingscache.h"
       
    17 #include "linkutil.h"
       
    18 
       
    19 /*static*/ CBTPairingsCache* CBTPairingsCache::NewL(MBTPairingsCacheObserver& aObserver, RBTRegServ& aRegServ)
       
    20 	{
       
    21 	CBTPairingsCache* self = new(ELeave) CBTPairingsCache(aObserver);
       
    22 	CleanupStack::PushL(self);
       
    23 	self->ConstructL(aRegServ);
       
    24 	CleanupStack::Pop(self);
       
    25 	return self;
       
    26 	}
       
    27 
       
    28 CBTPairingsCache::CBTPairingsCache(MBTPairingsCacheObserver& aObserver)
       
    29 	: iObserver(aObserver)
       
    30 	{
       
    31 	}
       
    32 
       
    33 void CBTPairingsCache::ConstructL(RBTRegServ& aRegServ)
       
    34 	{
       
    35 	iBTPairedBDAddrGetter = CBTPairedBDAddrGetter::NewL(*this, aRegServ);
       
    36 	DoUpdateCache();
       
    37 	}
       
    38 
       
    39 CBTPairingsCache::~CBTPairingsCache()
       
    40 	{
       
    41 	delete iBTPairedBDAddrGetter;
       
    42 	iPairedBDAddrs.Close();
       
    43 	}
       
    44 
       
    45 void CBTPairingsCache::UpdateCache()
       
    46 	{
       
    47 	// First we must cancel any outstanding request, as this will be called
       
    48 	// when the registry has been modified an an external (API) user, and
       
    49 	// so an in progress 'get' may have a stale view.
       
    50 	iBTPairedBDAddrGetter->Cancel();
       
    51 	DoUpdateCache();
       
    52 	}
       
    53 
       
    54 void CBTPairingsCache::DoUpdateCache()
       
    55 	{
       
    56     RemoveAllPairedDevices(); // Clear out the cache as it may be stale.
       
    57 	iCacheState = EUpdateOutstanding;
       
    58 	iBTPairedBDAddrGetter->Retrieve();
       
    59 	}
       
    60 
       
    61 CBTPairingsCache::TPairingState CBTPairingsCache::IsPaired(const TBTDevAddr& aBDAddr)
       
    62 	{
       
    63 	// We initially assume that there is no pairing to the remote device.
       
    64     CBTPairingsCache::TPairingState ret = ENotPaired;
       
    65     
       
    66     // We determine whether they are in our pairing cache or not.
       
    67     TBool inPairingCache = InPairingCache(aBDAddr);
       
    68 
       
    69 	// Now we do some additional work based on the state of the cache.
       
    70 	switch(iCacheState)
       
    71 		{
       
    72 	case EUpdateOutstanding:
       
    73 		// If an update has been requested then we make them
       
    74 		// wait for the answer.
       
    75 		ret = EDeferred;
       
    76 		break;
       
    77 	case EUpdateFailed:
       
    78 		// If we failed last time we should try again, and tell
       
    79 		// them to wait for the answer.
       
    80 		DoUpdateCache();
       
    81 		ret = EDeferred;
       
    82 		break;
       
    83 	case EValid:
       
    84 		// If the cache is valid then either we are paired or
       
    85 		// we aren't, the answer to which is based on whether they
       
    86 		// are in the cache or not.
       
    87 		break;
       
    88 	default:
       
    89 		Panic(EBTPairingsCacheBadState);
       
    90 		break;
       
    91 		}
       
    92 
       
    93 	// If we were already in the cache then that means there must be a pairing.
       
    94 	if(inPairingCache)
       
    95 		{
       
    96 		ret = EPaired;
       
    97 		}
       
    98 
       
    99 	// If we are deferring the decision about whether paired or not, then we 
       
   100 	// need to remember that we should inform the observer when we have 
       
   101 	// completed our attempt at getting an answer.
       
   102 	if(ret == EDeferred)
       
   103 		{
       
   104 		iDeferredDecision = ETrue;
       
   105 		}
       
   106 
       
   107 	return ret;
       
   108 	}
       
   109 
       
   110 TBool CBTPairingsCache::InPairingCache(const TBTDevAddr& aBDAddr)
       
   111 	{
       
   112 	return (PairedDeviceIndex(aBDAddr) >= 0) ? ETrue : EFalse;
       
   113 	}
       
   114 
       
   115 /**
       
   116 Wrapper for TBTDevAddr's == operation.
       
   117 This is needed by the TIdentityRelation parameter in RArray's Find method.
       
   118 */
       
   119 /*static*/ TBool CBTPairingsCache::AreBDAddrsEqual(const TBTDevAddr& aA, const TBTDevAddr& aB)
       
   120 	{
       
   121 	return aA == aB;
       
   122 	}
       
   123 
       
   124 /**
       
   125 Returns either the index of the remote device address in the
       
   126 paired device address list if the specified address is
       
   127 included therein or KErrNotFound if not
       
   128 */
       
   129 TInt CBTPairingsCache::PairedDeviceIndex(const TBTDevAddr& aBDAddr)
       
   130 	{
       
   131 	TIdentityRelation<TBTDevAddr> rel(AreBDAddrsEqual);
       
   132 	return iPairedBDAddrs.Find(aBDAddr, rel);
       
   133 	}
       
   134 
       
   135 TInt CBTPairingsCache::AddPairedDevice(const TBTDevAddr& aAddr)
       
   136 	{
       
   137     __ASSERT_DEBUG(aAddr!=0, Panic(EBTConnectionBadDeviceAddress));
       
   138 	
       
   139 	TInt err = KErrNone;
       
   140 	if(!InPairingCache(aAddr))
       
   141 		{
       
   142 		err = iPairedBDAddrs.Append(aAddr);
       
   143 		}
       
   144 	return err;
       
   145 	}
       
   146 
       
   147 void CBTPairingsCache::RemoveAllPairedDevices()
       
   148 	{
       
   149 	for(TInt i=iPairedBDAddrs.Count()-1; i>=0; i--)
       
   150 		{
       
   151 		iPairedBDAddrs.Remove(i);
       
   152 		}
       
   153 	}
       
   154 
       
   155 void CBTPairingsCache::InformObserver(TInt aError)
       
   156 	{
       
   157     // Ensure that we inform the observer only if they have been deferred.
       
   158 	if(iDeferredDecision)
       
   159 		{
       
   160 		iDeferredDecision = EFalse;
       
   161 		iObserver.MbpcoDeferredDecisionResolved(aError);
       
   162 		}
       
   163 	}
       
   164 
       
   165 /*virtual*/ void CBTPairingsCache::MbpdnAddPairedDevices(const RBTDeviceArray& aAddrs)
       
   166 	{
       
   167 	__ASSERT_DEBUG(iCacheState == EUpdateOutstanding, Panic(EBTPairingsCacheBadState));
       
   168 	
       
   169 	// check that the cache is still empty
       
   170 	__ASSERT_DEBUG(iPairedBDAddrs.Count() == 0, Panic(EBTPairingsCacheNotEmpty));
       
   171 	
       
   172 	TInt err = KErrNone;
       
   173 
       
   174 	TInt count = aAddrs.Count();
       
   175 	for (TInt i=0; i<count; i++)
       
   176 		{
       
   177 		err = AddPairedDevice(aAddrs[i]->BDAddr());
       
   178 		if(err != KErrNone)
       
   179 			{
       
   180 			break;
       
   181 			}
       
   182 		}
       
   183 
       
   184 	// We handle add failures ourselves.
       
   185 	iCacheState = (err == KErrNone) ? EValid : EUpdateFailed;
       
   186 
       
   187 	// We inform the observer, even if there was an error because it is
       
   188 	// possible that we managed to get the address they were after.
       
   189 	InformObserver(err);
       
   190 	}
       
   191 
       
   192 /*virtual*/ void CBTPairingsCache::MbpdnErrorInGettingPairedDevices(TInt aError)
       
   193 	{
       
   194 	__ASSERT_DEBUG(iCacheState == EUpdateOutstanding, Panic(EBTPairingsCacheBadState));
       
   195 	// Current cache should be ok - we should have cleared it before a getter is
       
   196 	// started.  This simply sets the flag to indicate that the current (empty) cache 
       
   197 	// is either complete if aErr is KErrNotFound (or KErrNone) or incomplete
       
   198 	// if aErr is anything else. In the latter case if the cache is needed in future 
       
   199 	// another getter should be kicked off.
       
   200 	TInt err = (aError != KErrNone && aError != KErrNotFound) ? aError : KErrNone;
       
   201 	if(err != KErrNone)
       
   202 		{
       
   203 		iCacheState = EUpdateFailed;
       
   204 		}
       
   205 	else
       
   206 		{
       
   207 		iCacheState = EValid;
       
   208 		}
       
   209 	
       
   210 	// Ensure that if we have been queried about the pairings and deferred the
       
   211 	// client, they must be informed.
       
   212 	InformObserver(err);
       
   213 	}
       
   214