// 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 thepaired device address list if the specified address isincluded therein or KErrNotFound if not*/TInt CBTPairingsCache::PairedDeviceIndex(const TBTDevAddr& aBDAddr) { TIdentityRelation<TBTDevAddr> 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; i<count; i++) { err = AddPairedDevice(aAddrs[i]->BDAddr()); 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); }