--- /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;
+ }