diff -r 000000000000 -r 29b1cd4cb562 bluetooth/btstack/linkmgr/pairingscache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bluetooth/btstack/linkmgr/pairingscache.cpp Fri Jan 15 08:13:17 2010 +0200 @@ -0,0 +1,214 @@ +// Copyright (c) 2007-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: +// +// Description: +// + +#include "pairingscache.h" +#include "linkutil.h" + +/*static*/ CBTPairingsCache* CBTPairingsCache::NewL(MBTPairingsCacheObserver& aObserver, RBTRegServ& aRegServ) + { + CBTPairingsCache* self = new(ELeave) CBTPairingsCache(aObserver); + CleanupStack::PushL(self); + self->ConstructL(aRegServ); + CleanupStack::Pop(self); + return self; + } + +CBTPairingsCache::CBTPairingsCache(MBTPairingsCacheObserver& aObserver) + : iObserver(aObserver) + { + } + +void CBTPairingsCache::ConstructL(RBTRegServ& aRegServ) + { + iBTPairedBDAddrGetter = CBTPairedBDAddrGetter::NewL(*this, aRegServ); + DoUpdateCache(); + } + +CBTPairingsCache::~CBTPairingsCache() + { + delete iBTPairedBDAddrGetter; + iPairedBDAddrs.Close(); + } + +void CBTPairingsCache::UpdateCache() + { + // First we must cancel any outstanding request, as this will be called + // when the registry has been modified an an external (API) user, and + // so an in progress 'get' may have a stale view. + iBTPairedBDAddrGetter->Cancel(); + DoUpdateCache(); + } + +void CBTPairingsCache::DoUpdateCache() + { + RemoveAllPairedDevices(); // Clear out the cache as it may be stale. + iCacheState = EUpdateOutstanding; + iBTPairedBDAddrGetter->Retrieve(); + } + +CBTPairingsCache::TPairingState CBTPairingsCache::IsPaired(const TBTDevAddr& aBDAddr) + { + // We initially assume that there is no pairing to the remote device. + CBTPairingsCache::TPairingState ret = ENotPaired; + + // We determine whether they are in our pairing cache or not. + TBool inPairingCache = InPairingCache(aBDAddr); + + // Now we do some additional work based on the state of the cache. + switch(iCacheState) + { + case EUpdateOutstanding: + // If an update has been requested then we make them + // wait for the answer. + ret = EDeferred; + break; + case EUpdateFailed: + // If we failed last time we should try again, and tell + // them to wait for the answer. + DoUpdateCache(); + ret = EDeferred; + break; + case EValid: + // If the cache is valid then either we are paired or + // we aren't, the answer to which is based on whether they + // are in the cache or not. + break; + default: + Panic(EBTPairingsCacheBadState); + break; + } + + // If we were already in the cache then that means there must be a pairing. + if(inPairingCache) + { + ret = EPaired; + } + + // If we are deferring the decision about whether paired or not, then we + // need to remember that we should inform the observer when we have + // completed our attempt at getting an answer. + if(ret == EDeferred) + { + iDeferredDecision = ETrue; + } + + return ret; + } + +TBool CBTPairingsCache::InPairingCache(const TBTDevAddr& aBDAddr) + { + return (PairedDeviceIndex(aBDAddr) >= 0) ? ETrue : EFalse; + } + +/** +Wrapper for TBTDevAddr's == operation. +This is needed by the TIdentityRelation parameter in RArray's Find method. +*/ +/*static*/ TBool CBTPairingsCache::AreBDAddrsEqual(const TBTDevAddr& aA, const TBTDevAddr& aB) + { + return aA == aB; + } + +/** +Returns either the index of the remote device address in the +paired device address list if the specified address is +included therein or KErrNotFound if not +*/ +TInt CBTPairingsCache::PairedDeviceIndex(const TBTDevAddr& aBDAddr) + { + TIdentityRelation rel(AreBDAddrsEqual); + return iPairedBDAddrs.Find(aBDAddr, rel); + } + +TInt CBTPairingsCache::AddPairedDevice(const TBTDevAddr& aAddr) + { + __ASSERT_DEBUG(aAddr!=0, Panic(EBTConnectionBadDeviceAddress)); + + TInt err = KErrNone; + if(!InPairingCache(aAddr)) + { + err = iPairedBDAddrs.Append(aAddr); + } + return err; + } + +void CBTPairingsCache::RemoveAllPairedDevices() + { + for(TInt i=iPairedBDAddrs.Count()-1; i>=0; i--) + { + iPairedBDAddrs.Remove(i); + } + } + +void CBTPairingsCache::InformObserver(TInt aError) + { + // Ensure that we inform the observer only if they have been deferred. + if(iDeferredDecision) + { + iDeferredDecision = EFalse; + iObserver.MbpcoDeferredDecisionResolved(aError); + } + } + +/*virtual*/ void CBTPairingsCache::MbpdnAddPairedDevices(const RBTDeviceArray& aAddrs) + { + __ASSERT_DEBUG(iCacheState == EUpdateOutstanding, Panic(EBTPairingsCacheBadState)); + + // check that the cache is still empty + __ASSERT_DEBUG(iPairedBDAddrs.Count() == 0, Panic(EBTPairingsCacheNotEmpty)); + + TInt err = KErrNone; + + TInt count = aAddrs.Count(); + for (TInt i=0; iBDAddr()); + if(err != KErrNone) + { + break; + } + } + + // We handle add failures ourselves. + iCacheState = (err == KErrNone) ? EValid : EUpdateFailed; + + // We inform the observer, even if there was an error because it is + // possible that we managed to get the address they were after. + InformObserver(err); + } + +/*virtual*/ void CBTPairingsCache::MbpdnErrorInGettingPairedDevices(TInt aError) + { + __ASSERT_DEBUG(iCacheState == EUpdateOutstanding, Panic(EBTPairingsCacheBadState)); + // Current cache should be ok - we should have cleared it before a getter is + // started. This simply sets the flag to indicate that the current (empty) cache + // is either complete if aErr is KErrNotFound (or KErrNone) or incomplete + // if aErr is anything else. In the latter case if the cache is needed in future + // another getter should be kicked off. + TInt err = (aError != KErrNone && aError != KErrNotFound) ? aError : KErrNone; + if(err != KErrNone) + { + iCacheState = EUpdateFailed; + } + else + { + iCacheState = EValid; + } + + // Ensure that if we have been queried about the pairings and deferred the + // client, they must be informed. + InformObserver(err); + } +