bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp
branchRCL_3
changeset 11 20fda83a6398
child 14 f8503e232b0c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp	Mon Mar 15 12:44:59 2010 +0200
@@ -0,0 +1,2020 @@
+// 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:
+// Implements backup and restore support for the Bluetooth Manager server.
+//
+
+#include <e32std.h>
+#include <e32base.h>
+#include <e32property.h>
+#include <f32file.h>
+#include <s32file.h>
+#include "btmanserverutil.h"
+#include "btmanserverburmgr.h"
+#include "BTManServer.h"
+
+#include "btmanclient.h"
+#include "btdevice.h"
+#include <bluetooth/hci/hcitypes.h>
+#include <bluetooth/logger.h>
+#include "BTSec.h"
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER);
+#endif
+
+
+/**
+Raises an EBTBURMgrInvalidState panic with state information encoded within the panic code.
+The first digit denotes the panic code (EBTBURMgrInvalidState).
+The second digit is a delimiter and is always 1.
+The next two digits represent the expected state
+The next digit again is a delimiter and is always 1.
+The final two digits represent the actual state. 
+
+For example, the panic code 7101100 indicates an EBTBURMgrInvalidState panic raised because the state
+machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state.
+**/
+void InvalidStatePanic(TBTBURState aExpectedState, TBTBURState aActualState)
+	{
+	LOG_STATIC_FUNC
+	User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidState*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aExpectedState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aActualState);
+	}
+
+/**
+Raises an EBTBURMgrInvalidStateTransition panic with state information encoded within the panic code.
+The first digit denotes the panic code (EBTBURMgrInvalidStateTransition).
+The second digit is a delimiter and is always 1.
+The next two digits represent the expected state
+The next digit again is a delimiter and is always 1.
+The final two digits represent the actual state. 
+
+For example, the panic code 6101100 indicates an EBTBURMgrInvalidStateTransition panic raised because the state
+machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state.
+**/
+void InvalidStateTransitionPanic(TBTBURState aCurrentState, TBTBUREvent aEvent)
+	{
+	LOG_STATIC_FUNC
+	User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidStateTransition*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aCurrentState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aEvent);
+	}
+
+
+/**
+CBTManServerBURMgr - Manages backup and restore support for the Bluetooth Manager server.
+**/
+
+/**
+Constructs a new instance of a CBTManServerBURMgr.
+An MBTBURNotify instance may be registered here for notifications. Ownership of the MBTBURNotify instance is not transferred.
+@see CBTManServerBURMgr::RequestBURNotification()
+**/
+CBTManServerBURMgr* CBTManServerBURMgr::NewL(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority)
+	{
+	LOG_STATIC_FUNC
+	CBTManServerBURMgr* self = new(ELeave) CBTManServerBURMgr(aBTManServer, aBURNotify, aPriority);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CBTManServerBURMgr::CBTManServerBURMgr(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) 
+	: CActive(aPriority), 
+	iBTManServer(aBTManServer),  
+	iBUROperationStartNotified(EFalse)
+	{
+	LOG_FUNC
+
+	RequestBURNotification(aBURNotify);
+	CActiveScheduler::Add(this);
+	}
+
+CBTManServerBURMgr::~CBTManServerBURMgr()
+	{
+	LOG_FUNC
+
+	Cancel();
+	iProperty.Close();
+
+	// Close any open session on BT Manager
+	NotifyAnyBUROperationStopped();
+		
+	// Members which either hold data or are NULL
+	delete iActiveBackupClient;
+	delete iActiveBackupDataClient;
+	delete iBackupHandler;
+	delete iRestoreHandler;
+	delete iLocalAddrFetcher;
+
+	// Member that is instantiated for entire lifetime of CBTManServerBURMgr
+	delete iStateMachine;
+	}
+
+void CBTManServerBURMgr::ConstructL()
+	{
+	LOG_FUNC
+
+	// Construct state machine
+	iStateMachine = CBTManServerBURMgrStateFactory::NewL(*this);
+	// Construction counts as a transition into the default state (EBTBURStateNormal) of the state machine.
+	// However, since this does nothing if no backup/restore cleanup is required, we do not need to execute the 
+	// state action.
+	
+	// Setup iProperty to catch BUR flag from Secure Backup Engine
+	LEAVEIFERRORL(iProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey));
+
+	// Subscribe to BUR P&S key to catch transitions
+	SubscribeToBackupRestoreKey();
+
+	// Also check flag now (it may have already transitioned)
+	TInt backupKeyValue = 0;
+	LEAVEIFERRORL(iProperty.Get(backupKeyValue));
+	TBURPartType backupState = GetBURPartType(backupKeyValue);	
+
+	// If we're not about to perform a restore, check if a restore file exists. If so, try to process restore file.
+	// The restore operation may not affect us, or may be postponed. In either case, we try to process the restore file
+	// again next time we start.
+	if (backupState != EBURRestoreFull && backupState != EBURRestorePartial)
+		{
+		// Delete any stale backup files
+		DeleteBackupFile();
+		// See if a restore file needs processing
+		CheckForRestoreFileL();
+		}
+
+	// Process flag
+	ProcessBackupState(backupState);
+	}
+
+/**
+Translates a given integer obtained from the KUidBackupRestoreKey P&S key to a TBURPartType value.
+This will validate the masked value to ensure that it falls within the range of the TBURPartType enum.
+In debug builds, a panic will be raised if this value is out of range.
+In release builds, EBURUnset is returned if the value is out of range.
+**/
+TBURPartType CBTManServerBURMgr::GetBURPartType(TInt aValue)
+	{
+	LOG_FUNC
+
+	switch (aValue & KBURPartTypeMask)
+		{
+	case EBURUnset:
+		return EBURUnset;
+	case EBURNormal:
+		return EBURNormal;
+	case EBURBackupFull:
+		return EBURBackupFull;
+	case EBURBackupPartial:
+		return EBURBackupPartial;
+	case EBURRestoreFull:
+		return EBURRestoreFull;
+	case EBURRestorePartial:
+		return EBURRestorePartial;
+	default:
+		__ASSERT_DEBUG(EFalse, PANIC(KBTBackupPanicCat, EBTBURMgrInvalidBackupRestoreState));
+		return EBURUnset;
+		}
+	}
+
+/**
+Attempts to locate a restore file in the private directory of this server.
+@return ETrue if the file can be found, EFalse otherwise.
+**/
+TBool CBTManServerBURMgr::RestoreFilePresent()
+	{
+	LOG_FUNC
+
+	RFs fsSession;
+	TInt err = fsSession.Connect();
+	if (err == KErrNone)
+		{
+		err = fsSession.SetSessionToPrivate(fsSession.GetSystemDrive());
+		if (err ==KErrNone)
+			{
+			TEntry entry;
+			err = fsSession.Entry(KBTManServerRestoreFileName, entry);
+			}
+
+		fsSession.Close();
+		}
+
+	// If restore file was found, err will be KErrNone
+	return (err == KErrNone);
+	}
+
+/**
+Checks for the existence of a restore file. If a restore file is found, then the local device address
+is feteched and processing of that restore file is initiated.
+**/
+void CBTManServerBURMgr::CheckForRestoreFileL()
+	{
+	LOG_FUNC
+
+	if (RestoreFilePresent())
+		{
+		// Fetch local address. When this is received, restore file processing will begin.
+		iLocalAddrFetcher = CBTLocalAddressFetcher::NewL(*this, iBTManServer.Registry());
+		iLocalAddrFetcher->FetchLocalAddress();
+		}
+	}
+
+/**
+Subscribes to the P&S flag provided by the Secure Backup Engine (to receive notification of backup/restore state changes).
+**/
+void CBTManServerBURMgr::SubscribeToBackupRestoreKey()
+	{
+	LOG_FUNC
+
+	iProperty.Subscribe(iStatus);
+	SetActive();	
+	}
+
+/**
+Processes a change in the backup/restore state of the device. 
+@param aBackupStateValue A value expressing the backup/restore state of the device. 
+**/
+void CBTManServerBURMgr::ProcessBackupState(TBURPartType aBURStateValue)
+	{
+	LOG_FUNC
+
+	iBURState = aBURStateValue;
+
+	switch (aBURStateValue)
+		{
+	case EBURBackupFull:
+		// Fall-through
+	case EBURBackupPartial:
+		iStateMachine->TransitionState(EBTBUREventBackup);
+		break;
+	case EBURRestoreFull:
+		// Fall-through
+	case EBURRestorePartial:
+		iStateMachine->TransitionState(EBTBUREventRestore);
+		break;
+	case EBURNormal:
+		iStateMachine->TransitionState(EBTBUREventNormal);
+		break;
+	default:	// EBURUnset
+		__ASSERT_DEBUG(aBURStateValue == EBURUnset, PANIC(KBTBackupPanicCat, EBTBURMgrUnknownBUREvent));
+		iStateMachine->TransitionState(EBTBUREventUnset);
+		}
+	}
+
+/**
+Registers an MBTBURNotify instance to receive notification of backup/restore operations starting and stopping.
+Ownership of this MBTBURNotify instance is not transferred.
+Any previous MBTBURNotify instance is deregistered on this method call.
+Supplying a NULL pointer will deregister the previously registered instance (if present).
+**/
+void CBTManServerBURMgr::RequestBURNotification(MBTBURNotify* aBURNotify)
+	{
+	LOG_FUNC
+
+	iBURNotify = aBURNotify;
+	}
+
+
+/**
+Receives a local address from a CBTLocalAddressFetcher instance.
+This will trigger processing of a pending restore file.
+**/
+void CBTManServerBURMgr::SetLocalAddress(TBTDevAddr& aLocalAddr)
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress));
+
+	// Use address only if it is non-zero.
+	if (aLocalAddr != TBTDevAddr())
+		{
+		// Take a copy
+		iLocalAddr = aLocalAddr;
+		// Attempt to start restore file processing.
+		// Note that this will fail if we are not in the normal state.
+		iStateMachine->TransitionState(EBTBUREventProcessRestoreFile);
+		}
+	}
+
+/**
+Receives notification that a restore file has been provided by the Secure Backup Engine.
+Upon receiving this notification, the restore file is renamed to have the appropriate extension and 
+the local device name is updated in the registry. The restore of the remote devices table is postponed
+until the next time BTManServer starts, so any ongoing BT connections are not affected.
+**/
+void CBTManServerBURMgr::RestoreFileReady()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
+
+	// Rename restore file
+	RenameBackupFileForRestore();
+	// Attempt to update local device name in the registry (best efforts only)
+	TRAP_IGNORE(UpdateLocalDeviceNameL());
+	}
+
+void CBTManServerBURMgr::HandleStateNormal()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateNormal, InvalidStatePanic(EBTBURStateNormal, iStateMachine->GetCurrentState()));
+
+	if (iActiveBackupClient)
+		{
+		// Backup or restore finished
+		if (iBackupHandler)
+			{
+			// Backup operation finished
+			// Delete backup file and destroy backup handler
+			DeleteBackupFile();
+			delete iBackupHandler;
+			iBackupHandler = NULL;
+			}
+		else
+			{
+			// Restore operation finished
+			delete iActiveBackupDataClient;
+			iActiveBackupDataClient = NULL;
+			}
+
+		// Destroy active backup client
+		delete iActiveBackupClient;
+		iActiveBackupClient = NULL;
+
+		// Notify that backup/restore operation has finished
+		NotifyBUROperationStopped();
+		}
+	}
+
+/**
+Determines if a BUR operation affects the Bluetooth Manager server.
+@return ETrue if a full backup or restore is ongoing, otherwise the return value
+given by CActiveBackupClient::DoesPartialBURAffectMeL()
+**/
+TBool CBTManServerBURMgr::DoesBURAffectMeL(CActiveBackupClient& aClient)
+	{
+	LOG_FUNC
+
+	if (iBURState == EBURBackupFull || iBURState == EBURRestoreFull)
+		{
+		return ETrue;
+		}
+	else
+		{
+		return aClient.DoesPartialBURAffectMeL();
+		}
+	}
+
+void CBTManServerBURMgr::HandleStateBackupRequestL()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState()));
+
+	// Determine if this backup operation affects us and transition to next state based on this outcome.
+	iActiveBackupClient = CActiveBackupClient::NewL();
+
+	if (DoesBURAffectMeL(*iActiveBackupClient))
+		{
+		// We're affected, proceed with backup
+		iStateMachine->TransitionState(EBTBUREventBackupProceed);
+		}
+	else
+		{
+		// We're not effected, don't do any backup handling
+		iStateMachine->TransitionState(EBTBUREventBackupReject);
+		}
+	}
+
+void CBTManServerBURMgr::HandleStateBackupRequestError()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState()));
+
+	// Transition to normal state
+	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
+	}
+
+void CBTManServerBURMgr::HandleStateBackupOngoingL()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState()));
+	__ASSERT_DEBUG(iActiveBackupClient, PANIC(KBTBackupPanicCat, EBTBURMgrActiveBackupClientNull));
+
+	// Provide notification that a BUR operation has started.
+	NotifyBUROperationStarted();
+
+	// Construct backup handler and prepare for backup
+	iBackupHandler = CBTBackupHandler::NewL(*this, iBTManServer.Registry());
+	iBackupHandler->CreateBackupFileL();
+
+	// Signal that we're ready for (passive) backup of prepared file
+	iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
+
+	// Next state transition will be invoked when BUR P&S key changes
+	}
+
+void CBTManServerBURMgr::HandleStateBackupOngoingError()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState()));
+
+	// Transition to normal state
+	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
+	}
+
+void CBTManServerBURMgr::HandleStateBackupIgnore()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupIgnore, InvalidStatePanic(EBTBURStateBackupIgnore, iStateMachine->GetCurrentState()));
+
+	// Destroy active backup client
+	delete iActiveBackupClient;
+	iActiveBackupClient = NULL;
+
+	// Next state transition will be invoked when BUR P&S key changes
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreRequestL()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState()));
+
+	// We do want a callback here. Even though the actual restore operation has been handled passively, we
+	// still need notificaton that the passive restore has completed (so we can then deal with the file).
+	iActiveBackupDataClient = CBTActiveBackupDataClient::NewL(*this);
+	iActiveBackupClient = CActiveBackupClient::NewL(iActiveBackupDataClient);
+
+	// Determine if this restore operation affects us and transition to next state based on this outcome
+	if (DoesBURAffectMeL(*iActiveBackupClient))
+		{
+		// We're affected, proceed with restore
+		iStateMachine->TransitionState(EBTBUREventRestoreProceed);
+		}
+	else
+		{
+		// We're not effected, don't do any restore handling
+		iStateMachine->TransitionState(EBTBUREventRestoreReject);
+		}
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreRequestError()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState()));
+	
+	// Transition to normal state
+	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreOngoingL()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
+
+	// Cancel any local address requests
+	if (iLocalAddrFetcher)
+		{
+		iLocalAddrFetcher->Cancel();
+		}
+
+	// Provide notification that a BUR operation has started.
+	NotifyBUROperationStarted();
+
+	// Signal that we're ready for active restore of prepared file
+	// (note that no data is actively restored, but we still need to invoke this method)
+	iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
+
+	// Next state transition will be invoked when BUR P&S key changes
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreOngoingError()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
+
+	// Transition to normal state
+	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreIgnore()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreIgnore, InvalidStatePanic(EBTBURStateRestoreIgnore, iStateMachine->GetCurrentState()));
+
+	// Destroy active backup client
+	delete iActiveBackupClient;
+	delete iActiveBackupDataClient;
+	iActiveBackupClient = NULL;
+	iActiveBackupDataClient = NULL;
+
+	// Next state transition will be invoked when BUR P&S key changes
+	}
+
+void CBTManServerBURMgr::HandleStateProcessRestoreFileL()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState()));
+
+	// Start restore file processing
+	iRestoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer);
+	iRestoreHandler->RestoreRemoteDeviceTableL(iLocalAddr);
+
+	iStateMachine->TransitionState(EBTBUREventProcessRestoreFileComplete);
+	}
+
+void CBTManServerBURMgr::HandleStateProcessRestoreFileError(TInt aError)
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState()));
+
+	// Delete restore handler
+	delete iRestoreHandler;
+	iRestoreHandler = NULL;
+	
+	// If aError is anything other than KErrNoMemory, then delete restore file.
+	// OOM errors may be temporary, and a subsequent restore attempt may succeed.
+	if (aError != KErrNoMemory)
+		{
+		DeleteRestoreFile();
+		}
+
+	// Transition to normal state
+	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
+	}
+
+void CBTManServerBURMgr::HandleStateRestoreFileProcessingComplete()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreFileProcessingComplete, InvalidStatePanic(EBTBURStateRestoreFileProcessingComplete, iStateMachine->GetCurrentState()));
+	
+	// Delete restore file (we're now done with it)
+	DeleteRestoreFile();
+
+	// Delete restore handler
+	delete iRestoreHandler;
+	iRestoreHandler = NULL;
+
+	iStateMachine->TransitionState(EBTBUREventRestoreFileTransitionNormal);
+	}
+
+/**
+Sends notification to a registered MBTBURNotify instance that a backup or restore operation has started.
+@see CBTManServerBURMgr::RequestBURNotification()
+**/
+void CBTManServerBURMgr::NotifyBUROperationStarted()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(!iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartAlreadyNotified));
+	
+	if (!iBUROperationStartNotified)
+		{
+		iBUROperationStartNotified = ETrue;
+
+		if (iBURNotify)
+			{
+			iBURNotify->BUROperationStarted();
+			}
+		}
+	}
+
+/**
+Sends notification to the MBTBURNotify instance that a backup or restore operation has started. 
+This should correspond to a call to NotifyBUROperationStarted().
+@see CBTManServerBURMgr::RequestBURNotification()
+**/
+void CBTManServerBURMgr::NotifyBUROperationStopped()
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartNotNotified));
+	
+	if (iBUROperationStartNotified)
+		{
+		iBUROperationStartNotified = EFalse;
+
+		if (iBURNotify)
+			{
+			iBURNotify->BUROperationStopped();
+			}
+		}
+	}
+
+/**
+Sends notification to the MBTBURNotify instance that a backup or restore operation has started. 
+This will send notification only if NotifyBUROperationStarted() has been called without a corresponding 
+call to NotifyBUROperationStopped().
+This is intended for use in error situations only.
+**/
+void CBTManServerBURMgr::NotifyAnyBUROperationStopped()
+	{
+	LOG_FUNC
+
+	// We deliberately want to fail silently here if no stop notification is expected.
+	if (iBUROperationStartNotified)
+		{
+		iBUROperationStartNotified = EFalse;
+
+		if (iBURNotify)
+			{
+			iBURNotify->BUROperationStopped();
+			}
+		}
+	}
+
+/**
+Utility function to delete a named file from the private directory of this process on the system drive.
+This is a best-efforts attempt which fails silently on error.
+@param aFileName The name of the file to delete.
+**/
+void CBTManServerBURMgr::DeleteFile(const TDesC& aFileName)
+	{
+	LOG_FUNC
+
+	RFs fsSession;
+	// Attempt to delete file
+	// This is best-efforts, failing silently on any error (as there is no remedy action that we can take).
+	if (fsSession.Connect() == KErrNone)
+		{
+		if (fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()) == KErrNone)
+			{
+			// Try to ensure read-only and system attributes are not set
+			TUint attrs;
+			TInt err = fsSession.Att(aFileName, attrs);
+			if (err == KErrNone)
+				{
+				// Unset the files read-only and system attributes if these are set.
+				TUint unsetAttrs = (attrs & KEntryAttReadOnly) | (attrs & KEntryAttSystem);
+				if (unsetAttrs != KEntryAttNormal)
+					{
+					err = fsSession.SetAtt(aFileName, KEntryAttNormal, unsetAttrs);
+					}
+
+				// Attempt to delete the file, if we've managed to successfully retrieve and reset the file attributes. 
+				// Note that this is best-efforts.
+				if (err == KErrNone)
+					{
+					static_cast<void>(fsSession.Delete(aFileName));
+					}
+				}
+			}
+
+		fsSession.Close();
+		}
+	}	
+
+/**
+Deletes the backup file (with name KBTManServerBackupFileName) from the private directory of this process on the system drive.
+This is a best-efforts attempt which fails silently on error.
+**/
+void CBTManServerBURMgr::DeleteBackupFile()
+	{
+	LOG_FUNC
+
+	DeleteFile(KBTManServerBackupFileName);
+	}
+
+/**
+Deletes the restore file (with name KBTManServerRestoreFileName) from the private directory of this process on the system drive.
+This is a best-efforts attempt which fails silently on error.
+**/
+void CBTManServerBURMgr::DeleteRestoreFile()
+	{
+	LOG_FUNC
+
+	DeleteFile(KBTManServerRestoreFileName);
+	}
+
+/**
+Renames a restored backup file from KBTManServerBackupFileName to KBTManServerRestoreFileName.
+This facilitates processing of the restore file when the Bluetooth Manager server next starts.
+This is a best-efforts attempt, as no remedial action can be taken if this operation fails.
+**/
+void CBTManServerBURMgr::RenameBackupFileForRestore()
+	{
+	LOG_FUNC
+
+	// Delete any previous restore file
+	DeleteRestoreFile();
+	
+	RFs fsSession;
+	if (fsSession.Connect() == KErrNone)
+		{
+		static_cast<void>(fsSession.Rename(KBTManServerBackupFileName, KBTManServerRestoreFileName));
+		fsSession.Close();
+		}
+	}
+
+/**
+Parses the restore file and updates the loal device name in the registry.
+This update takes place as soon as the restore file is available, regardless of whether or not the local device
+address matches that held in the registry. If the local device name has already been set to a non-default value,
+then it is not modified.
+**/
+void CBTManServerBURMgr::UpdateLocalDeviceNameL()
+	{
+	LOG_FUNC
+		
+	CBTRestoreHandler* restoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer);
+	CleanupStack::PushL(restoreHandler);
+
+	restoreHandler->RestoreLocalDeviceNameL();
+
+	CleanupStack::PopAndDestroy(restoreHandler);
+	}
+
+void CBTManServerBURMgr::RunL()
+	{
+	LOG_FUNC
+	
+	if (iStatus == KErrNone)
+		{
+		// Subscribe to catch the next transition
+		SubscribeToBackupRestoreKey();
+
+		// Handle this event
+		TInt backupKeyValue = 0;
+		LEAVEIFERRORL(iProperty.Get(backupKeyValue));
+		TBURPartType backupState = GetBURPartType(backupKeyValue);
+
+		ProcessBackupState(backupState);
+		}
+	}
+
+TInt CBTManServerBURMgr::RunError(TInt /*aError*/)
+	{
+	LOG_FUNC
+
+	// Problem occured in obtaining backup key value.
+	// Ignore the error, as there is nothing we can do.
+	return KErrNone;
+	}
+
+void CBTManServerBURMgr::DoCancel()
+	{
+	LOG_FUNC
+	
+	// Cancel our subscription
+	iProperty.Cancel();
+	}
+
+/**
+ CBTBackupHandler - Handles the task of backing up the BT registry into a backup file ready for passive backup.
+ **/
+CBTBackupHandler* CBTBackupHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry)
+	{
+	LOG_STATIC_FUNC
+
+	CBTBackupHandler* result = new(ELeave) CBTBackupHandler(aBURMgr, aRegistry);
+	CleanupStack::PushL(result);
+	result->ConstructL();
+	CleanupStack::Pop(result);
+	return result;
+	}
+
+CBTBackupHandler::CBTBackupHandler(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) 
+	: iBURMgr(aBURMgr), 
+	iRegistry(aRegistry)
+	{
+	LOG_FUNC
+	}
+
+void CBTBackupHandler::ConstructL()
+	{
+	LOG_FUNC
+
+	iRegistryData=CBTRegistryBURData::NewL();
+	}
+
+CBTBackupHandler::~CBTBackupHandler()
+	{
+	LOG_FUNC
+
+	delete iRegistryData;
+	}
+
+void CBTBackupHandler::CreateBackupFileL()
+	{
+	LOG_FUNC
+
+	// Collect backup registry data
+	iRegistryData->ReadFromRegistryL(iRegistry);
+	
+	// Only continue if the registry is populated (i.e. it may be in its default state, which does not need to be backed up).
+	// Determine this by examining the local device address stored in the registry. The default registry has this set to 0x0.
+	if (iRegistryData->IsLocalAddressNonZeroL())
+		{
+		// Construct backup file in private directory.
+		RFs fsSession;
+		LEAVEIFERRORL(fsSession.Connect());
+		CleanupClosePushL(fsSession);
+		LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()));
+		// Create private path if it does not already exist.
+		LEAVEIFERRORL(fsSession.CreatePrivatePath(fsSession.GetSystemDrive()));
+
+		RFileWriteStream fStream;
+		// Create backup file, overwriting if necessary (don't care about previous backup files).
+		LEAVEIFERRORL(fStream.Replace(fsSession, KBTManServerBackupFileName, EFileWrite));
+		fStream.PushL();
+			    
+		// Write out data
+		iRegistryData->WriteToStreamL(fStream);
+		fStream.CommitL();
+
+		CleanupStack::PopAndDestroy(2, &fsSession);
+		}
+	}
+
+/**
+ CBTRestoreHandler - Handles the task of restoring the BT registry from a restore file given by passive restore.
+ **/
+CBTRestoreHandler* CBTRestoreHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer)
+	{
+	LOG_STATIC_FUNC
+
+	CBTRestoreHandler* result = new(ELeave) CBTRestoreHandler(aBURMgr, aManServer);
+	CleanupStack::PushL(result);
+	result->ConstructL();
+	CleanupStack::Pop(result);
+	return result;
+	}
+
+CBTRestoreHandler::CBTRestoreHandler(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) 
+	: iBURMgr(aBURMgr), 
+	iManServer(aManServer)
+	{
+	LOG_FUNC
+	}
+	
+void CBTRestoreHandler::ConstructL()
+	{
+	LOG_FUNC
+
+	iRegistryData = CBTRegistryBURData::NewL();
+	}
+
+CBTRestoreHandler::~CBTRestoreHandler()
+	{
+	LOG_FUNC
+
+	delete iRegistryData;
+	}
+
+void CBTRestoreHandler::RestoreLocalDeviceNameL()
+	{
+	LOG_FUNC
+
+	LoadRestoreDataL();
+
+	// If the local device name is still default, restore without validating the local address
+	// (otherwise we will not be able to restore this field before the next stack start, which may cause problems with some UIs)
+	CBTRegistry& registry = iManServer.Registry();
+	if (iRegistryData->WriteLocalDeviceNameToRegistryL(registry))
+		{
+		NotifyLocalTableChange();
+		}
+	}
+
+void CBTRestoreHandler::RestoreRemoteDeviceTableL(TBTDevAddr& aLocalAddr)
+	{
+	LOG_FUNC
+	__ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress));
+
+	LoadRestoreDataL();
+    
+	// Compare local address held in restore file with our local address
+	if (iRegistryData->IsLocalAddressEqualL(aLocalAddr))
+		{
+    		// Proceed with restore of remote devices table
+		CBTRegistry& registry = iManServer.Registry();
+
+		TInt noRemoteDevices = iRegistryData->CountRemoteDevicesL();
+		for (TInt i = 0; i < noRemoteDevices; i++)
+			{
+			if (iRegistryData->WriteRemoteDeviceToRegistryL(registry, i))
+				{
+				NotifyRemoteTableChangeL(iRegistryData->GetRemoteDeviceL(i).BDAddr());
+				}
+			}
+		}
+	}
+
+void CBTRestoreHandler::LoadRestoreDataL()
+	{
+	LOG_FUNC
+
+	// Read restore file
+	RFs fsSession;
+	LEAVEIFERRORL(fsSession.Connect());
+	CleanupClosePushL(fsSession);
+	LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()));
+	// Assuming private directory exists at this point
+	
+	RFileReadStream fStream;
+	LEAVEIFERRORL(fStream.Open(fsSession, KBTManServerRestoreFileName, EFileRead));
+	fStream.PushL();
+
+	// Read in data
+	iRegistryData->ReadFromStreamL(fStream);
+
+	// Cleanup
+	CleanupStack::PopAndDestroy(2, &fsSession);	//fStream and fsSession
+	}
+
+/**
+Sends a notification that the persistence table has been changed.
+The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. 
+**/
+void CBTRestoreHandler::NotifyLocalTableChange()
+	{
+	LOG_FUNC
+	
+	// Notify the P&S key that the remote devices table has changed
+	iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeLocalTable);
+	}
+
+/**
+Sends a notification that a device in the remote devices table has been changed.
+The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. 
+Interested parties can also use RBTRegistry::NotifyViewChange() to detect if the change affects their view.
+**/
+void CBTRestoreHandler::NotifyRemoteTableChangeL(const TBTDevAddr& aAddress)
+	{
+	LOG_FUNC
+	
+	// Construct SQL constraint which selects the device
+	RBTDbQuery query;
+	CleanupClosePushL(query);
+	query.FindDeviceL(aAddress);
+
+	HBufC* conDes = query.ConstraintBuf().AllocLC();
+
+	// Notify the P&S key that the remote devices table has changed
+	iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeRemoteTable);
+
+	// Signal notifiers waiting on view change
+	iManServer.NotifyViewChange(*conDes);
+
+	// Cleanup constDes and query
+	CleanupStack::PopAndDestroy(2, &query);
+	}
+
+/**
+CBTRegistryBURData - manages data from the Bluetooth registry that is to be backed up or restored.
+**/
+CBTRegistryBURData* CBTRegistryBURData::NewL()
+	{
+	LOG_STATIC_FUNC
+
+	CBTRegistryBURData* self = new(ELeave) CBTRegistryBURData();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CBTRegistryBURData::CBTRegistryBURData() 
+	: iHasRegistryData(EFalse)
+	{
+	LOG_FUNC
+	}
+
+CBTRegistryBURData::~CBTRegistryBURData()
+	{
+	LOG_FUNC
+
+	if (iRemoteDevices)	// Dont use ClearRegistryData() here as leave may have occured in ReadFromRegistryL() or ReadFromStreamL()
+		{
+		// Destroy all CBTDevices in iRemoteDevices (necessary before array deletion for CArrayPtrFlat)
+		iRemoteDevices->ResetAndDestroy();
+		}
+
+	delete iLocalDevice;
+	delete iRemoteDevicesSid;
+	delete iRemoteDevices;
+	}
+
+void CBTRegistryBURData::ConstructL()
+	{
+	LOG_FUNC
+
+	iRemoteDevicesSid = new (ELeave) CArrayFixFlat<TSecureId>(1);
+	iRemoteDevices = new(ELeave) CBTDeviceArray(1);
+	}
+	
+/**
+Writes the registry data held in this instance to a given stream.
+This does not write those registry fields which contain unset values.
+@param aStream The stream to write the registry data to.
+**/
+void CBTRegistryBURData::WriteToStreamL(RWriteStream& aStream) const
+	{
+	LOG_FUNC
+
+	// Writes registry data out to a given stream, avoiding any use of class externalisation.
+	if (HasRegistryData())
+		{
+		// This follows a specific file-format (tied to the registry version information), which is documented seperately.
+
+		// We should already have the following information for the local device.
+		__ASSERT_DEBUG(iLocalDevice->IsValidAddress(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
+
+		// Write out version information
+		aStream.WriteUint32L(iRegistryVersionMajor);
+		aStream.WriteUint32L(iRegistryVersionMinor);
+
+		// Persistence table:
+		// Local device address and name only (both are mandatory).
+		aStream.WriteL(iLocalDevice->Address().Des(), KBTDevAddrSize);
+
+		__ASSERT_DEBUG(iLocalDevice->DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
+		aStream.WriteUint8L(iLocalDevice->DeviceName().Length());
+		aStream.WriteL(iLocalDevice->DeviceName(), iLocalDevice->DeviceName().Length());
+
+		// Remote devices table
+		TInt rdCount=CountRemoteDevicesL();
+
+		aStream.WriteUint32L(rdCount);
+		for (TInt i = 0; i < rdCount; i++)
+			{
+			const CBTDevice& nextRemDev = GetRemoteDeviceL(i);
+			const TBTNamelessDevice& nextRemDevNameless = nextRemDev.AsNamelessDevice();
+
+			__ASSERT_DEBUG(nextRemDev.IsValidBDAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
+
+			// Work out what is set and derive bitmask (can use TBTDeviceSet here as is public)
+			TUint32 rdSetMask = TBTNamelessDevice::EAddress;
+			if (nextRemDev.IsValidDeviceClass())
+				{
+				rdSetMask |= TBTNamelessDevice::EDeviceClass;
+				}
+			if (nextRemDev.IsValidLinkKey())
+				{
+				rdSetMask |= TBTNamelessDevice::ELinkKey;
+				}
+			if (nextRemDev.IsValidGlobalSecurity())
+				{
+				rdSetMask |= TBTNamelessDevice::EGlobalSecurity;
+				}
+			if (nextRemDevNameless.IsValidPageScanRepMode())
+				{
+				rdSetMask |= TBTNamelessDevice::EPageScanRepMode;
+				}
+			if (nextRemDevNameless.IsValidPageScanMode())
+				{
+				rdSetMask |= TBTNamelessDevice::EPageScanMode;
+				}
+			if (nextRemDevNameless.IsValidPageScanPeriodMode())
+				{
+				rdSetMask |= TBTNamelessDevice::EPageScanPeriodMode;
+				}
+			if (nextRemDevNameless.IsValidClockOffset())
+				{
+				rdSetMask |= TBTNamelessDevice::EClockOffset;
+				}
+			if (nextRemDev.IsValidUsed())
+				{
+				rdSetMask |= TBTNamelessDevice::EUsed;
+				}
+			if (nextRemDev.IsValidSeen())
+				{
+				rdSetMask |= TBTNamelessDevice::ESeen;
+				}
+			if (nextRemDev.IsValidPassKey())
+				{
+				rdSetMask |= TBTNamelessDevice::EPassKey;
+				}
+			if (nextRemDev.IsValidUiCookie())
+				{
+				rdSetMask |= TBTNamelessDevice::EUiCookie;
+				}
+			if (nextRemDev.IsValidDeviceName())
+				{
+				rdSetMask |= CBTDevice::EDeviceName;
+				}
+			if (nextRemDev.IsValidFriendlyName())
+				{
+				rdSetMask |= CBTDevice::EFriendlyName;
+				}
+			// Now write out bitmask
+			aStream.WriteUint32L(rdSetMask);
+
+			// Write valid setting for next remote device
+			aStream.WriteUint32L(GetRemoteDeviceEntrySidL(i));
+			aStream.WriteL(nextRemDev.BDAddr().Des(), KBTDevAddrSize);
+			if (rdSetMask & TBTNamelessDevice::EDeviceClass)
+				{
+				aStream.WriteUint32L(nextRemDev.DeviceClass().DeviceClass());
+				}
+			if (rdSetMask & TBTNamelessDevice::ELinkKey)
+				{
+				const TBTLinkKey& nextRemDevLinkKey = nextRemDev.LinkKey();
+				aStream.WriteL(nextRemDevLinkKey, KHCILinkKeySize);
+				aStream.WriteUint8L(nextRemDev.LinkKeyType());
+				}
+			if (rdSetMask & TBTNamelessDevice::EGlobalSecurity)
+				{
+				TBTDeviceSecurity nextRemDevGlobSec = nextRemDev.GlobalSecurity();
+				aStream.WriteUint8L(nextRemDevGlobSec.SecurityValue());
+				aStream.WriteUint32L(nextRemDevGlobSec.PasskeyMinLength());
+				}
+			if (rdSetMask & TBTNamelessDevice::EPageScanRepMode)
+				{
+				aStream.WriteUint8L(nextRemDevNameless.PageScanRepMode());
+				}
+			if (rdSetMask & TBTNamelessDevice::EPageScanMode)
+				{
+				aStream.WriteUint8L(nextRemDevNameless.PageScanMode());
+				}
+			if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode)
+				{
+				aStream.WriteUint8L(nextRemDevNameless.PageScanPeriodMode());
+				}
+			if (rdSetMask & TBTNamelessDevice::EClockOffset)
+				{
+				aStream.WriteUint16L(nextRemDevNameless.ClockOffset());
+				}
+			if (rdSetMask & TBTNamelessDevice::EUsed)
+				{
+				const TInt64& used = nextRemDev.Used().Int64();
+				aStream.WriteInt32L(I64HIGH(used));
+				aStream.WriteInt32L(I64LOW(used));
+				}
+			if (rdSetMask & TBTNamelessDevice::ESeen)
+				{
+				const TInt64& seen = nextRemDev.Seen().Int64();
+				aStream.WriteInt32L(I64HIGH(seen));
+				aStream.WriteInt32L(I64LOW(seen));
+				}
+			if (rdSetMask & TBTNamelessDevice::EPassKey)
+				{
+				const TBTPinCode& nextRemDevPassKey = nextRemDev.PassKey();
+				__ASSERT_DEBUG(nextRemDevPassKey.Length() == KHCIPINCodeSize + 1, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorUnexpectedLength));
+				aStream.WriteL(nextRemDevPassKey, KHCIPINCodeSize + 1);
+				}
+			if (rdSetMask & TBTNamelessDevice::EUiCookie)
+				{
+				aStream.WriteUint32L(nextRemDev.UiCookie());
+				}
+			if (rdSetMask & CBTDevice::EDeviceName)
+				{
+				__ASSERT_DEBUG(nextRemDev.DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
+				aStream.WriteUint8L(nextRemDev.DeviceName().Length());
+				aStream.WriteL(nextRemDev.DeviceName(), nextRemDev.DeviceName().Length());
+				}
+			if (rdSetMask & CBTDevice::EFriendlyName)
+				{
+				__ASSERT_DEBUG(nextRemDev.FriendlyName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
+				aStream.WriteUint8L(nextRemDev.FriendlyName().Length());
+				aStream.WriteL(nextRemDev.FriendlyName(), nextRemDev.FriendlyName().Length());
+				}
+			}
+		}
+	else
+		{
+		User::Leave(KErrNotFound);
+		}
+	}
+
+/**
+Reads registry data from a given stream and stores within this instance.
+Any registry data currently held is cleared first.
+@param aStream The stream to ready the registry data from.
+**/
+void CBTRegistryBURData::ReadFromStreamL(RReadStream& aStream)
+	{
+	LOG_FUNC
+
+	// This follows a specific file-format (tied to the registry version information), which is documented seperately.
+	
+	// Note that we dont make *ANY* assumptions as to what data should always be available, since the restore file could be corrupt.
+	// We will fail the restore if it turns out we do not have enough information, or if we have invalid information.
+	
+	// WARNING: When a new registry version is produced, this implementaton of backup/restore support will need modification.
+	// This assert should be updated to include all supported registry versions.
+	__ASSERT_DEBUG(KRegistryDBVersionMajor == 1 && KRegistryDBVersionMinor == 2, PANIC(KBTBackupPanicCat, EBTBURMgrUnsupportedRegistryVersion));
+	
+	// Extract version information and continue if we can handle it.
+	TUint32 regVersionMajor = aStream.ReadUint32L();
+	TUint32 regVersionMinor = aStream.ReadUint32L();
+	if (regVersionMajor == KRegistryDBVersionMajor && regVersionMinor == KRegistryDBVersionMinor)
+		{
+		// We support this version and this version only - read in registry data
+		ClearRegistryData();
+
+		iLocalDevice = new(ELeave) TBTLocalDevice;
+		
+		// Note version information for this registry
+		iRegistryVersionMajor = regVersionMajor;
+		iRegistryVersionMinor = regVersionMinor;
+
+		// Persistence table:
+		// Local device address and name only (both fields are mandatory).
+		TBTDevAddr address;
+		TPtr8 addrPtr(address.Des());
+		aStream.ReadL(addrPtr, KBTDevAddrSize);
+		if (addrPtr.Length() == KBTDevAddrSize)
+			{
+			iLocalDevice->SetAddress(address);
+			}
+		else
+			{
+			User::Leave(KErrCorrupt);
+			}
+
+		TInt deviceNameLength = static_cast<TInt>(aStream.ReadUint8L());
+		if (deviceNameLength <= KMaxBluetoothNameLen)
+			{
+			RBuf8 deviceName;
+			deviceName.CreateL(KMaxBluetoothNameLen);
+			CleanupClosePushL(deviceName);
+
+			aStream.ReadL(deviceName,deviceNameLength);
+			if (deviceName.Length() == deviceNameLength)
+				{
+				iLocalDevice->SetDeviceName(deviceName);
+				}
+			else
+				{
+				User::Leave(KErrCorrupt);
+				}
+			CleanupStack::PopAndDestroy(&deviceName);
+			}
+		else
+			{
+			User::Leave(KErrCorrupt);
+			}
+		
+		// Remote devices table:
+		TInt rdCount = aStream.ReadUint32L();
+		for (TInt i = 0; i < rdCount; i++)
+			{
+			// First read bitmask of available data
+			TUint32 rdSetMask = aStream.ReadUint32L();
+
+			// Then read available data from file and store
+			CBTDevice *rdInstance = CBTDevice::NewLC();
+			TBTNamelessDevice& rdNamelessDevInstance = rdInstance->AsNamelessDevice();
+			TSecureId rdSid = aStream.ReadUint32L();
+
+			// Remote BT address is mandatory
+			if (rdSetMask & TBTNamelessDevice::EAddress)
+				{
+				TBTDevAddr rdAddr;
+				TPtr8 rdAddrPtr(rdAddr.Des());
+				aStream.ReadL(rdAddrPtr, KBTDevAddrSize);
+
+				// Ensure address is of required length and is non-zero
+				if (rdAddrPtr.Length() == KBTDevAddrSize && rdAddr != TBTDevAddr())
+					{
+					rdInstance->SetDeviceAddress(rdAddr);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+			else
+				{
+				User::Leave(KErrCorrupt);
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EDeviceClass)
+				{
+				TBTDeviceClass rdClass = TBTDeviceClass(aStream.ReadUint32L());
+				rdInstance->SetDeviceClass(rdClass);
+				}
+
+			if (rdSetMask & TBTNamelessDevice::ELinkKey)
+				{
+				TBTLinkKey rdLinkKey;
+				aStream.ReadL(rdLinkKey, KHCILinkKeySize);
+				if (rdLinkKey.Length() == KHCILinkKeySize)
+					{
+					TUint8 rdLinkKeyType = static_cast<TBTLinkKeyType>(aStream.ReadUint8L());
+					// Ensure value is in the valid range (ELinkKeyCombination is zero so (pointless) comparison with this gives warnings).
+					if (rdLinkKeyType <= ELinkKeyDebug)
+						{
+						rdInstance->SetLinkKey(rdLinkKey, static_cast<TBTLinkKeyType>(rdLinkKeyType));
+						}
+					else
+						{
+						User::Leave(KErrCorrupt);
+						}
+
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EGlobalSecurity)
+				{
+				TBTDeviceSecurity rdGlobSec;
+				TUint8 globSecValue = aStream.ReadUint8L();
+				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
+				if (globSecValue <= KBTBURMgrMaxGlobalSecurityValue)
+					{
+					rdGlobSec.SetSecurityValue(globSecValue);
+
+					TUint32 passKeyMinLen = aStream.ReadUint32L();
+
+					if (passKeyMinLen <= KHCIPINCodeSize)
+						{
+						rdGlobSec.SetPasskeyMinLength(passKeyMinLen);
+						rdInstance->SetGlobalSecurity(rdGlobSec);
+						}
+					else
+						{
+						User::Leave(KErrCorrupt);
+						}
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EPageScanRepMode)
+				{
+				TUint8 rdPageScanRepMode = aStream.ReadUint8L();
+				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
+				if (rdPageScanRepMode <= EPageScanModeR2)
+					{
+					rdNamelessDevInstance.SetPageScanRepMode(rdPageScanRepMode);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EPageScanMode)
+				{
+				TUint8 rdPageScanMode = aStream.ReadUint8L();
+				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
+				if (rdPageScanMode <= KBTBURMgrMaxPageScanMode)
+					{
+					rdNamelessDevInstance.SetPageScanMode(rdPageScanMode);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode)
+				{
+				TUint8 rdPageScanPeriodMode = aStream.ReadUint8L();
+				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
+				if (rdPageScanPeriodMode <= KBTBURMgrMaxPageScanPeriodMode)
+					{
+					rdNamelessDevInstance.SetPageScanPeriodMode(rdPageScanPeriodMode);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EClockOffset)
+				{
+				TUint16 rdClockOffset = aStream.ReadUint16L();
+				rdNamelessDevInstance.SetClockOffset(rdClockOffset);
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EUsed)
+				{
+				TInt32 usedU = aStream.ReadInt32L();
+				TInt32 usedL = aStream.ReadInt32L();
+				TInt64 rdUsed = MAKE_TINT64(usedU, usedL);
+				rdNamelessDevInstance.SetUsed(rdUsed);
+				}
+
+			if (rdSetMask & TBTNamelessDevice::ESeen)
+				{
+				TInt32 seenU = aStream.ReadInt32L();
+				TInt32 seenL = aStream.ReadInt32L();
+				TInt64 rdSeen = MAKE_TINT64(seenU, seenL);
+				rdNamelessDevInstance.SetSeen(rdSeen);	
+				}
+
+			if (rdSetMask & TBTNamelessDevice::EPassKey)
+				{
+				TBTPinCode rdPassKey;
+				aStream.ReadL(rdPassKey, KHCIPINCodeSize + 1);
+				if (rdPassKey.Length() == KHCIPINCodeSize + 1)
+					{
+					rdInstance->SetPassKey(rdPassKey);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+			
+			if (rdSetMask & TBTNamelessDevice::EUiCookie)
+				{
+				TUint32 rdUiCookie = aStream.ReadUint32L();
+				rdNamelessDevInstance.SetUiCookie(rdUiCookie);
+				}
+
+			if (rdSetMask & CBTDevice::EDeviceName)
+				{
+				TInt rdNameLen = static_cast<TInt>(aStream.ReadUint8L());
+				if (rdNameLen <= KMaxBluetoothNameLen)
+					{
+					RBuf8 rdName;
+					rdName.CreateL(KMaxBluetoothNameLen);
+					CleanupClosePushL(rdName);
+					
+					aStream.ReadL(rdName, rdNameLen);
+					if (rdName.Length() == rdNameLen)
+						{
+						rdInstance->SetDeviceNameL(rdName);
+						}
+					else
+						{
+						User::Leave(KErrCorrupt);
+						}
+					CleanupStack::PopAndDestroy(&rdName);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+
+			if (rdSetMask & CBTDevice::EFriendlyName)
+				{
+				TInt rdFriendlyNameLen = static_cast<TInt>(aStream.ReadUint8L());
+				if (rdFriendlyNameLen <= KMaxFriendlyNameLen)
+					{
+					RBuf rdFriendlyName;
+					rdFriendlyName.CreateL(KMaxFriendlyNameLen);
+					CleanupClosePushL(rdFriendlyName);
+
+					aStream.ReadL(rdFriendlyName, rdFriendlyNameLen);
+					if (rdFriendlyName.Length() == rdFriendlyNameLen)
+						{
+						rdInstance->SetFriendlyNameL(rdFriendlyName);
+						}
+					else
+						{
+						User::Leave(KErrCorrupt);
+						}
+					CleanupStack::PopAndDestroy(&rdFriendlyName);
+					}
+				else
+					{
+					User::Leave(KErrCorrupt);
+					}
+				}
+			
+			// Data now stored, add rdInstance to our remote devices list
+			iRemoteDevices->AppendL(rdInstance);
+			iRemoteDevicesSid->AppendL(rdSid);
+			CleanupStack::Pop(rdInstance);
+			}
+
+		// Mark that we now have registry data 
+		iHasRegistryData = ETrue;
+		}
+	}
+
+/**
+Reads registry data from the registry into this instance.
+Any existing registry data held in this instance is cleared first.
+@param aRegistry The CBTRegistry instance to use for registry access.
+**/
+void CBTRegistryBURData::ReadFromRegistryL(CBTRegistry& aRegistry)
+	{
+	LOG_FUNC
+
+	ClearRegistryData();
+
+	// The meta information from our registry is known.
+	iRegistryVersionMajor = KRegistryDBVersionMajor;
+	iRegistryVersionMinor = KRegistryDBVersionMinor;
+
+	// Persistence table
+	iLocalDevice = aRegistry.GetLocalDeviceL();
+
+	// Remote device table
+	// Create a view on the table.
+	RBTDbQuery query;
+	CleanupClosePushL(query);
+	TBTRegistrySearch searchCriteria;
+	searchCriteria.FindAll();
+	query.SearchL(searchCriteria);
+	TDbBookmark bookmark;
+	RDbView* view = aRegistry.OpenViewL(query, bookmark);
+	CleanupCloseDeletePushL(view);
+
+	// Populate iRemoteDevices from the view.
+	while (!view->AtEnd())
+		{
+		CBTDevice *next = aRegistry.GetNextDeviceL(*view, bookmark, ETrue);
+		CleanupStack::PushL(next);
+		
+		// CBTRegisty::CreatingProcessUidL() requires a rowset with exactly one row.
+		// So we have to requery for this device to get a singular row.
+		TDbBookmark singleBookmark;
+		RDbView* singleView = aRegistry.OpenDeviceL(next->BDAddr(), singleBookmark);
+		CleanupCloseDeletePushL(singleView);
+		TSecureId nextSid = aRegistry.CreatingProcessUidL(*singleView);
+		CleanupStack::PopAndDestroy(singleView);
+		
+		iRemoteDevices->AppendL(next);
+		iRemoteDevicesSid->AppendL(nextSid);
+		
+		CleanupStack::Pop(next);	// iRemoteDevices now takes ownership
+		}
+
+	CleanupStack::PopAndDestroy(2, &query);	// view and query
+
+	// Mark that we now have registry data 
+	iHasRegistryData = ETrue;
+	}
+
+/**
+Updates the persistence table of the registry with local device name held in this instance
+if the registry currently holds a default name.
+@param aRegistry The CBTRegistry instance to use for registry access.
+@return ETrue if an update was made to the registry.
+**/
+TBool CBTRegistryBURData::WriteLocalDeviceNameToRegistryL(CBTRegistry& aRegistry) const
+	{
+	LOG_FUNC
+
+	TBool updateDone = EFalse;
+
+	// Update device name only if the registry has a default name 
+	TBTLocalDevice defaultDevice;
+	TRAP_IGNORE(aRegistry.GetDefaultDeviceFromIniL(defaultDevice));
+
+	if (!defaultDevice.IsValidDeviceName())
+		{
+		// Could not obtain a default name - use KDefaultLocalName instead
+		defaultDevice.SetDeviceName(KDefaultLocalName);
+		}
+
+	TBTLocalDevice* localDevice = aRegistry.GetLocalDeviceL();
+	CleanupStack::PushL(localDevice);
+
+	if (localDevice->DeviceName() == defaultDevice.DeviceName())
+		{
+		// Local device name is default, update with restored value.
+		localDevice->SetDeviceName(GetLocalDeviceNameL());
+		aRegistry.UpdateLocalDeviceL(*localDevice);
+		updateDone = ETrue;
+		}
+
+	CleanupStack::PopAndDestroy(localDevice);
+
+	return updateDone;
+	}
+
+/**
+Updates an entry of the remote devices table of the registry with data held in this instance.
+If the remote device already exists in the registry, the registry version is updated only if it
+does not hold a link key.
+Otherwise, the remote device is added to the registry.
+@param aRegistry The CBTRegistry instance to use for registry access.
+@param aDeviceIndex The remote device held in this CBTRegistryBURData instance to be written to the registry.
+@return ETrue if an update was made to the registry.
+**/
+TBool CBTRegistryBURData::WriteRemoteDeviceToRegistryL(CBTRegistry& aRegistry, TInt aDeviceIndex) const
+	{
+	LOG_FUNC
+
+	TBool updateDone = EFalse;
+	
+	// Get device and SID
+	const CBTDevice& nextRemDevice = GetRemoteDeviceL(aDeviceIndex);
+	TSecureId nextRemDeviceSid = GetRemoteDeviceEntrySidL(aDeviceIndex);
+
+	// Try to add device to registry. If this fails with KErrAlreadExists, then update existing device.
+	TRAPD(err, aRegistry.CreateDeviceL(nextRemDevice, nextRemDevice.IsValidUiCookie(), nextRemDeviceSid));
+
+	if (err == KErrNone)
+		{
+		// New device added successfully
+		updateDone = ETrue;
+		}
+	else if (err == KErrAlreadyExists)
+		{
+		// Device already exists. Extract and examine
+		TDbBookmark bookmark;
+		RDbView* view = aRegistry.OpenDeviceL(nextRemDevice.BDAddr(), bookmark);
+		CleanupCloseDeletePushL(view);
+		CBTDevice *regDev = aRegistry.GetNextDeviceL(*view, bookmark, ETrue);
+		CleanupStack::PushL(regDev);
+
+		if (!regDev->IsValidLinkKey())
+			{
+			// No link key - safe to restore remote device from file.
+			view->FirstL();
+			aRegistry.UpdateDeviceL(*view, nextRemDevice);
+			updateDone = ETrue;
+			}
+
+		CleanupStack::PopAndDestroy(2, view);
+		}
+	else
+		{
+		// Unexpected error - pass upward for handling
+		User::Leave(err);
+		}
+
+	return updateDone;
+	}
+
+void CBTRegistryBURData::GetRegistryVersionL(TUint32& aRegistryVersionMajor, TUint32& aRegistryVersionMinor) const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData())
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	aRegistryVersionMajor = iRegistryVersionMajor;
+	aRegistryVersionMinor = iRegistryVersionMinor;
+	}
+
+const TDesC8& CBTRegistryBURData::GetLocalDeviceNameL() const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData())
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	__ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
+	return iLocalDevice->DeviceName();
+	}
+
+TBool CBTRegistryBURData::IsLocalAddressNonZeroL() const
+	{
+	LOG_FUNC
+
+	TBTDevAddr zeroAddr;
+	return !IsLocalAddressEqualL(zeroAddr);
+	}
+
+TBool CBTRegistryBURData::IsLocalAddressEqualL(TBTDevAddr& aAddr) const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData())
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	__ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
+	return (iLocalDevice->Address() == aAddr);
+	}
+
+TInt CBTRegistryBURData::CountRemoteDevicesL() const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData())
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
+	return iRemoteDevices->Count();
+	}
+
+const CBTDevice& CBTRegistryBURData::GetRemoteDeviceL(TInt aDeviceIndex) const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevices->Count())))
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
+	return *(iRemoteDevices->At(aDeviceIndex));
+	}
+
+TSecureId CBTRegistryBURData::GetRemoteDeviceEntrySidL(TInt aDeviceIndex) const
+	{
+	LOG_FUNC
+
+	if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevicesSid->Count())))
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
+	return iRemoteDevicesSid->At(aDeviceIndex);
+	}
+
+/**
+Clears any registry data stored internally within this instance.
+If no data is stored, this method does nothing.
+**/
+void CBTRegistryBURData::ClearRegistryData()
+	{
+	LOG_FUNC
+
+	// This is a no-op if we have no registry data to clear
+	if (HasRegistryData())
+		{
+		// Clear data held previously
+		iRemoteDevicesSid->Reset();
+		iRemoteDevices->ResetAndDestroy();
+		delete iLocalDevice;
+		iLocalDevice = NULL;
+
+		iHasRegistryData = EFalse;
+		}
+	}
+
+/**
+CBTLocalAddressFetcher - Fetches the local device address, or waits for the addresss to become available, and 
+passes to CBTManServerBURMgr.
+**/
+CBTLocalAddressFetcher* CBTLocalAddressFetcher::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority)
+	{
+	LOG_STATIC_FUNC
+
+	CBTLocalAddressFetcher* result = new(ELeave) CBTLocalAddressFetcher(aBURMgr, aRegistry, aPriority);
+	CleanupStack::PushL(result);
+	result->ConstructL();
+	CleanupStack::Pop(result);
+	return result;
+	}
+
+CBTLocalAddressFetcher::CBTLocalAddressFetcher(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) 
+	: CActive(aPriority), 
+	iBURMgr(aBURMgr), 
+	iRegistry(aRegistry)
+	{
+	LOG_FUNC
+
+	CActiveScheduler::Add(this);
+	}
+
+CBTLocalAddressFetcher::~CBTLocalAddressFetcher()
+	{
+	LOG_FUNC
+
+	// Cancel any outstanding requests
+	Cancel();
+	iProperty.Close();
+	}
+
+void CBTLocalAddressFetcher::ConstructL()
+	{
+	LOG_FUNC
+
+	// Attach to KPropertyKeyBluetoothGetLocalDeviceAddress
+	LEAVEIFERRORL(iProperty.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress));
+	}
+
+void CBTLocalAddressFetcher::FetchLocalAddress()
+	{
+	LOG_FUNC
+
+	// Subscribe for local address, in case we need to wait
+	SubscribeToGetLocalDeviceAddressKey();	
+
+	// Attempt to read the BT address from KPropertyKeyBluetoothGetLocalDeviceAddress key
+	// If key is not found or yields a zero address then try the registry.
+	// If the registry also holds a zero address then wait for notification from the P&S key.
+	TBuf8<KBTDevAddrSize> btAddrDes;
+	TBTDevAddr btAddr;
+	TInt err = iProperty.Get(btAddrDes);
+	
+	if (err != KErrNone)
+		{
+		// Key does not exist or could not be read.
+		// Stack may not be loaded, so now try registry.
+		// Ignore any errors; if we can't read this now then we will wait for the stack.
+		TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL());
+		}
+	else
+		{
+		// Convert btAddrDes to TBTDevAddr if it has the required size.
+		if (btAddrDes.Length() == KBTDevAddrSize)
+			{
+			btAddr = btAddrDes;	
+			}
+
+		if (btAddr == TBTDevAddr())
+			{
+			// Key exists, so stack is loaded, but address is zero, so now try registry
+			// Ignore any errors; if we can't read this now then we will wait for the stack.
+			TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL());
+			}
+		}
+	
+	// We have tried our best to get the local address.
+	// If this is non-zero, provide to CBTManServerBURMgr instance. 
+	// Otherwise, wait on P&S key
+	if (btAddr != TBTDevAddr())
+		{
+		// We have a non-zero address.
+		// Cancel subscription and inform CBTManServerBURMgr.
+		Cancel();
+		iBURMgr.SetLocalAddress(btAddr);
+		}	
+	}
+
+void CBTLocalAddressFetcher::SubscribeToGetLocalDeviceAddressKey()
+	{
+	LOG_FUNC
+
+	// Subscribe to KPropertyKeyBluetoothGetLocalDeviceAddress key
+	iProperty.Subscribe(iStatus);
+	SetActive();
+	}
+
+TBTDevAddr CBTLocalAddressFetcher::GetLocalAddressFromRegistryL()
+	{
+	LOG_FUNC
+	
+	TBTLocalDevice* regLocalDevice=iRegistry.GetLocalDeviceL();
+	TBTDevAddr result=regLocalDevice->Address();
+	delete regLocalDevice;
+	
+	return result;	
+	}
+
+void CBTLocalAddressFetcher::RunL()
+	{
+	LOG_FUNC
+
+	if (iStatus == KErrNone)
+		{
+		// Obtain address and send to CBTManServerBURMgr
+		TBuf8<KBTDevAddrSize> btAddrDes;
+		TBTDevAddr btAddr;
+		TInt err = iProperty.Get(btAddrDes);
+				
+		__ASSERT_DEBUG(err == KErrNone, PANIC(KBTBackupPanicCat, EBTBURMgrUnexpectedRPropertyError));
+		
+		if (err == KErrNone) 
+			{
+			btAddr = btAddrDes;
+			iBURMgr.SetLocalAddress(btAddr);
+			}
+		}
+	}
+
+void CBTLocalAddressFetcher::DoCancel()
+	{
+	LOG_FUNC
+
+	// Cancel our subscription
+	iProperty.Cancel();
+	}
+
+/**
+CBTActiveBackupDataClient - Active callback implementation (for restore notification)
+**/
+CBTActiveBackupDataClient* CBTActiveBackupDataClient::NewL(CBTManServerBURMgr& aBURMgr)
+	{
+	LOG_STATIC_FUNC
+
+	CBTActiveBackupDataClient* result = new (ELeave) CBTActiveBackupDataClient(aBURMgr);
+	return result;
+	}
+
+CBTActiveBackupDataClient::CBTActiveBackupDataClient(CBTManServerBURMgr& aBURMgr) 
+	: iBURMgr(aBURMgr)
+	{
+	LOG_FUNC
+	}
+
+CBTActiveBackupDataClient::~CBTActiveBackupDataClient()
+	{
+	LOG_FUNC
+	}
+
+// Backup methods (not used)
+void CBTActiveBackupDataClient::AllSnapshotsSuppliedL()
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::ReceiveSnapshotDataL(TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/)
+	{
+	LOG_FUNC
+
+ 	//Not supported
+	User::Leave(KErrNotSupported);	
+	}
+ 
+TUint CBTActiveBackupDataClient::GetExpectedDataSize(TDriveNumber /*aDrive*/)
+	{
+	LOG_FUNC
+
+	//Not supported - so expected size can be 0
+	return 0;
+	}
+ 
+void CBTActiveBackupDataClient::GetSnapshotDataL(TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::InitialiseGetBackupDataL(TDriveNumber /*aDrive*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::GetBackupDataSectionL(TPtr8& /*aBuffer*/, TBool& /*aFinished*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+         
+//Restore methods (only the notification method RestoreComplete() is used)
+ 
+void CBTActiveBackupDataClient::InitialiseRestoreBaseDataL(TDriveNumber /*aDrive*/)
+	{
+	LOG_FUNC
+
+	//Note that we are doing a base restore.
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::RestoreBaseDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}	
+ 
+void CBTActiveBackupDataClient::InitialiseRestoreIncrementDataL(TDriveNumber /*aDrive*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::RestoreIncrementDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/)
+	{
+	LOG_FUNC
+
+	//Not supported
+	User::Leave(KErrNotSupported);
+	}
+ 
+void CBTActiveBackupDataClient::RestoreComplete(TDriveNumber aDrive)
+	{
+	LOG_FUNC
+
+	// Allow CBTManServerBURMgr instance to handle arrival of restore file.
+	if (aDrive == RFs::GetSystemDrive())
+		{
+		iBURMgr.RestoreFileReady();
+		}
+	}
+ 
+         
+//General methods
+ 
+void CBTActiveBackupDataClient::TerminateMultiStageOperation()
+	{
+	LOG_FUNC
+
+	//Dont care - we will see the operation is cancelled when normal or unset mode is invoked.
+	}
+ 
+//Test methods
+ 
+TUint CBTActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/)
+	{
+	LOG_FUNC
+
+	//Return an invariant checksum
+	return 0;
+	}