diff -r 000000000000 -r bde4ae8d615e os/ossrv/lowlevellibsandfws/apputils/src/babackup.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/ossrv/lowlevellibsandfws/apputils/src/babackup.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,699 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include +#include +#include +#include +#include "Baksrvs.h" +#include +#include +#include + +#define UNUSED_VAR(a) a = a + +const TUid KServerUid3={0x10004900}; +const TInt KBADefaultPriority = CActive::EPriorityUserInput; +_LIT(KBackupSrvName,"baksrvs"); + +// +// class RBaBackupSession +// + +const TInt KNumConnectRetries =10; + + +class RBaBackupSession : public RSessionBase + { +public: + TInt Connect(); + void RegisterForNotifications(TRequestStatus& aStatus) const; + void DeregisterForNotifications() const; + void GetEvent(TDes& aFileName,MBackupObserver::TFileLockFlags& aFileFlag) const; + void CloseAllFiles(MBackupObserver::TFileLockFlags aFlags,TRequestStatus& aStatus) const; + void RestartApps() const; + TInt CloseFile(const TDesC& aFileName,MBackupObserver::TFileLockFlags aFlags) const; + void RestartFile(const TDesC& aFileName) const; + TInt NotifyChangeFileLock(const TDesC& aFileName) const; + void NotifyChangeFileLockCancel(const TDesC& aFileName) const; + void CloseServer() const; + void NotifyBackupOperation(const TBackupOperationAttributes& aBackupOperationAttributes); + TBool IsBackupOperationRunning() const; + void BackupOperationEventReady(TRequestStatus& aStatus, TPckgBuf& aBackupOperationAttributes) const; + void CancelOutstandingEventForBackupOperation() const; + void GetBackupOperationEvent(TBackupOperationAttributes& aBackupOperationAttributes) const; + void SetBackupOperationObserverIsPresent(TBool aObserverIsPresent) const; +private: + TInt StartServer(); + }; + +TInt RBaBackupSession::Connect() + { + TInt err=KErrNone; + TInt retry=KNumConnectRetries; + FOREVER + { + err=CreateSession(__BACKUP_SERVER_NAME_V2,TVersion(KBakServMajorVN,KBakServMinorVN,KBakServBuildVN),KBakServMessageSlots); + if ((--retry>0) && ((err==KErrNotFound) || (err==KErrServerTerminated))) + { + err = StartServer(); + if ((err!=KErrNone) && (err!=KErrAlreadyExists)) + { + break; + } + } + else + { + break; + } + } + return err; + } + +TInt RBaBackupSession::StartServer() + { + const TUidType serverUid(KNullUid,KNullUid,KServerUid3); + TInt error=KErrNone; + RProcess server; + error = server.Create(KBackupSrvName,KNullDesC,serverUid); + if(error!=KErrNone) + return error; + TRequestStatus stat; + server.Rendezvous(stat); + if (stat!=KRequestPending) + server.Kill(0); // abort startup + else + server.Resume(); // logon OK - start the server + User::WaitForRequest(stat); // wait for start or death + // we can't use the 'exit reason' if the server panicked as this + // is the panic 'reason' and may be '0' which cannot be distinguished + // from KErrNone + error=(server.ExitType()==EExitPanic) ? KErrGeneral : stat.Int(); + server.Close(); + return error; + } + + +void RBaBackupSession::RegisterForNotifications(TRequestStatus& aStatus) const + { + SendReceive(EBakOpCodeEventReady,aStatus); + } + +void RBaBackupSession::DeregisterForNotifications() const + { + SendReceive(EBakOpCodeStopNotifications); + } + +void RBaBackupSession::GetEvent(TDes& aFileName,MBackupObserver::TFileLockFlags& aFileFlag) const + { + TBuf buf; + if (SendReceive(EBakOpCodeGetEvent,TIpcArgs(&buf))!=KErrServerTerminated) + { + TBuf<1> num=buf.Left(1); + buf.Delete(0,1); + aFileName=buf; + aFileFlag=(MBackupObserver::TFileLockFlags)(num[0]-'0'); + } + } + +void RBaBackupSession::CloseAllFiles(MBackupObserver::TFileLockFlags aFlags,TRequestStatus& aStatus) const + { + SendReceive(EBakOpCodeCloseAllFiles,TIpcArgs(aFlags),aStatus); + } + +void RBaBackupSession::RestartApps() const + { + SendReceive(EBakOpCodeRestartAll); + } + +TInt RBaBackupSession::CloseFile(const TDesC& aFileName,MBackupObserver::TFileLockFlags aFlags) const + { + const TInt err=SendReceive(EBakOpCodeCloseFile,TIpcArgs(aFileName.Length(),&aFileName,aFlags)); + return err; + } + +void RBaBackupSession::RestartFile(const TDesC& aFileName) const + { + SendReceive(EBakOpCodeRestartFile,TIpcArgs(aFileName.Length(),&aFileName)); + } + +TInt RBaBackupSession::NotifyChangeFileLock(const TDesC& aFileName) const + { + return SendReceive(EBakOpCodeNotifyLockChange,TIpcArgs(aFileName.Length(),&aFileName)); + } + +void RBaBackupSession::NotifyChangeFileLockCancel(const TDesC& aFileName) const + { + SendReceive(EBakOpCodeNotifyLockChangeCancel,TIpcArgs(aFileName.Length(),&aFileName)); + } + +void RBaBackupSession::CloseServer() const + { + Send(EBakOpCodeCloseServer); + } + +void RBaBackupSession::NotifyBackupOperation(const TBackupOperationAttributes& aBackupOperationAttributes) + { + TPckgC backupOpAttPkg(aBackupOperationAttributes); + SendReceive(EBakOpCodeNotifyBackupOperation, TIpcArgs(&backupOpAttPkg)); + } + +void RBaBackupSession::CancelOutstandingEventForBackupOperation() const + { + SendReceive(EBakOpCodeCancelOutstandingBackupOperationEvent); + } + +TBool RBaBackupSession::IsBackupOperationRunning() const + { + TBool isRunning=EFalse; + TPckg pkg(isRunning); + SendReceive(EBakOpCodeGetBackupOperationState, TIpcArgs(&pkg)); + return pkg(); + } + +void RBaBackupSession::BackupOperationEventReady(TRequestStatus& aStatus, TPckgBuf& aBackupOperationAttributes) const + { + SendReceive(EBakOpCodeBackupOperationEventReady,TIpcArgs(&aBackupOperationAttributes),aStatus); + } + +void RBaBackupSession::GetBackupOperationEvent(TBackupOperationAttributes& aBackupOperationAttributes) const + { + TPckg backupOpAttPkg(aBackupOperationAttributes); + SendReceive(EBakOpCodeGetBackupOperationEvent, TIpcArgs(&backupOpAttPkg)); + } + +void RBaBackupSession::SetBackupOperationObserverIsPresent(TBool aObserverIsPresent) const + { + Send(EBakOpCodeSetBackupOperationObserverIsPresent, TIpcArgs(aObserverIsPresent)); + } + +// +// class CBaLockChangeNotifier +// + +NONSHARABLE_CLASS(CBaLockChangeNotifier) : public CActive + { +public: + static CBaLockChangeNotifier* NewL(RBaBackupSession& aBackupSession); + ~CBaLockChangeNotifier(); + void AddL(const TDesC& aFileName, MBackupObserver& aObserver); + void Remove(const TDesC& aFileName); +protected: + void StartNotifications(); + void StopNotifications(); +private: // from CActive + void DoCancel(); + void RunL(); +private: + CBaLockChangeNotifier(RBaBackupSession& aBackupSession); + void DoRunL(); + TInt Find(const TDesC& aFileName) const; +private: + class TFileItem + { + public: + TFileItem(HBufC* aFile,MBackupObserver& aObserver); + public: + HBufC* iFile; + MBackupObserver& iObserver; + }; +private: + RBaBackupSession& iBackupSession; + RArray iFileItems; + }; + +CBaLockChangeNotifier::TFileItem::TFileItem(HBufC* aFile,MBackupObserver& aObserver) + : iFile(aFile), + iObserver(aObserver) + {} + +CBaLockChangeNotifier* CBaLockChangeNotifier::NewL(RBaBackupSession& aBackupSession) + { // static + CBaLockChangeNotifier* self=new(ELeave) CBaLockChangeNotifier(aBackupSession); + CActiveScheduler::Add(self); + return self; + } + +CBaLockChangeNotifier::~CBaLockChangeNotifier() + { + Cancel(); + + const TInt count=iFileItems.Count(); + for (TInt ii=0;iiMatchF(fileName)==0) + { + TRAPD(r,fileItem.iObserver.ChangeFileLockL(*fileItem.iFile,fileFlag)); + if (r!=KErrNone && err==KErrNone) + { + err=r; + } + } + } + User::LeaveIfError(err); + } + +TInt CBaLockChangeNotifier::Find(const TDesC& aFileName) const + { + TInt index=KErrNotFound; + const TInt count=iFileItems.Count(); + for (TInt ii=0;ii iObservers; + RBaBackupSession& iBackupSession; + TPckgBuf iBackupOperationAttributes; + }; + + +CBaBackupOperationNotifier* CBaBackupOperationNotifier::NewL(RBaBackupSession& aBackupSession) + { // static + CBaBackupOperationNotifier* self=new(ELeave) CBaBackupOperationNotifier(aBackupSession); + CActiveScheduler::Add(self); + return self; + } + +CBaBackupOperationNotifier::~CBaBackupOperationNotifier() + { + Cancel(); + iObservers.Reset(); + iObservers.Close(); + } + +void CBaBackupOperationNotifier::AddBackupOperationObserverL(MBackupOperationObserver& aBackupOperationObserver) + { + const TInt index = iObservers.Find(&aBackupOperationObserver); + if (index == KErrNotFound) + { + User::LeaveIfError(iObservers.Append(&aBackupOperationObserver)); + if (iBackupSession.IsBackupOperationRunning()) + { + TBackupOperationAttributes backupOperationAttributes; + iBackupSession.GetBackupOperationEvent(backupOperationAttributes); + aBackupOperationObserver.HandleBackupOperationEventL(backupOperationAttributes); + } + } + Queue(); + } + +void CBaBackupOperationNotifier::RemoveBackupOperationObserver(MBackupOperationObserver& aBackupOperationObserver) + { + const TInt index = iObservers.Find(&aBackupOperationObserver); + if (index != KErrNotFound) + { + iObservers.Remove(index); + if (iObservers.Count() == 0) + { + iBackupSession.CancelOutstandingEventForBackupOperation(); + iBackupSession.SetBackupOperationObserverIsPresent(EFalse); + } + } + } + +void CBaBackupOperationNotifier::DoCancel() + { + TBackupOperationAttributes backupOperationAttributes; + iBackupSession.GetBackupOperationEvent(backupOperationAttributes); + const TInt count = iObservers.Count(); + for (TInt index=0; indexHandleBackupOperationEventL(backupOperationAttributes)); + UNUSED_VAR(errCode); + } + iBackupSession.CancelOutstandingEventForBackupOperation(); + } + +void CBaBackupOperationNotifier::RunL() + { + const TInt status=iStatus.Int(); + if (status!=KErrCancel && iObservers.Count()>0) + { + TRAPD(err,DoRunL()); + if (err!=KErrServerTerminated) + { + Queue(); + } + User::LeaveIfError(err); + } + } + +CBaBackupOperationNotifier::CBaBackupOperationNotifier(RBaBackupSession& aBackupSession) + : CActive(EPriorityStandard), iBackupSession(aBackupSession) + {} + +void CBaBackupOperationNotifier::Queue() + { + if (!IsActive()) + { + iStatus=KRequestPending; + SetActive(); + iBackupSession.SetBackupOperationObserverIsPresent(ETrue); + iBackupSession.BackupOperationEventReady(iStatus, iBackupOperationAttributes); + } + } + +void CBaBackupOperationNotifier::DoRunL() + { + const TInt status=iStatus.Int(); + if (status<0) + { + User::Leave(status); + } + const TInt count = iObservers.Count(); + for (TInt index=0; indexHandleBackupOperationEventL(iBackupOperationAttributes()); + } + } + +// +// class CBaBackupSessionWrapper +// + +/** + * Returns a newly created CBaBackupSessionWrapper, passing ownership immediately + */ +EXPORT_C CBaBackupSessionWrapper* CBaBackupSessionWrapper::NewL() + { // static + CBaBackupSessionWrapper* self=new(ELeave) CBaBackupSessionWrapper(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); // self + return self; + } + +/** + * D'tor. Any files or apps that have been closed will be restarted + */ +EXPORT_C CBaBackupSessionWrapper::~CBaBackupSessionWrapper() + { + delete iLockChangeNotifier; + delete iBackupOperationNotifier; + if (iBackupSession) + { + iBackupSession->Close(); + delete iBackupSession; + } + } + +/** +Register the specified file to the server. The given observer will be called back when +the lock state of the file should be modified + +@param aFileName the name of the file to be observed. +@param aObserver the observer which will be called back when the lock state of the file should be modified. + +@leave KErrServerBusy if the server is busy with the other client or under CloseAll operation. KErrNoMemory +if not enough memory to register this file. +*/ +EXPORT_C void CBaBackupSessionWrapper::RegisterFileL(const TDesC& aFileName,MBackupObserver& aObserver) + { + if (!iLockChangeNotifier) + { + iLockChangeNotifier=CBaLockChangeNotifier::NewL(*iBackupSession); + } + + __ASSERT_ALWAYS(iLockChangeNotifier, Panic(EBafPanicNullPointer)); + iLockChangeNotifier->AddL(aFileName,aObserver); + } + +/** + * Stop sending this client requests to alter the lock state of aFileName + */ +EXPORT_C void CBaBackupSessionWrapper::DeregisterFile(const TDesC& aFileName) + { + if(iLockChangeNotifier) + iLockChangeNotifier->Remove(aFileName); + } + +/** + Closes all non-system apps and signal all registered files to have their locks altered according to aFlags. + Returns immediately before having finished all processing. aStatus will be completed when everything is + closed or closing has completed. Possible error codes are + KErrNoMemory - Not enough memory to signal all apps/files to close + KErrServerBusy - Another client has some files closed - No-one else should attempt any backup operation + KErrLocked - Not all apps were successfully closed + In all cases, an undefined number of apps/files may have been closed and backup may still be possible although + install/restore operations should not be attempted. + + @param aFlags the file lock state to request the other clients with. + @param aStatus the request status to be completed when all files have been closed. + @publishedPartner + @released + @capability WriteDeviceData + */ +EXPORT_C void CBaBackupSessionWrapper::CloseAll(MBackupObserver::TFileLockFlags aFlags,TRequestStatus& aStatus) + { + iBackupSession->CloseAllFiles(aFlags,aStatus); + } + +/** + * Opposite of CloseAll. Can safely be called nothing has been closed by this client + * + * @publishedPartner + * @released + * @capability WriteDeviceData + */ +EXPORT_C void CBaBackupSessionWrapper::RestartAll() + { + iBackupSession->RestartApps(); + } + +/** + Close or reduce use of aFileName depending on the state of aFlags. + + @param aFileName the name of the file to be closed / changed the file lock state. + @param aFlag the file lock state to change to. + @leave KErrNoMemory if not enough memory to signal the files to close. KErrServerIsBusy if another client + has some files being closed. + @publishedPartner + @released + @capability WriteDeviceData + */ +EXPORT_C void CBaBackupSessionWrapper::CloseFileL(const TDesC& aFileName,MBackupObserver::TFileLockFlags aFlags) + { + User::LeaveIfError(iBackupSession->CloseFile(aFileName,aFlags)); + } + +/** + * Opposite of CloseFileL. Can be safely called if CloseFileL hasn't been called before + * + * @publishedPartner + * @released + * @capability WriteDeviceData + */ +EXPORT_C void CBaBackupSessionWrapper::RestartFile(const TDesC& aFileName) + { + iBackupSession->RestartFile(aFileName); + } + +CBaBackupSessionWrapper::CBaBackupSessionWrapper() + {} + +void CBaBackupSessionWrapper::ConstructL() + { + iBackupSession=new(ELeave) RBaBackupSession(); + User::LeaveIfError(iBackupSession->Connect()); + } + + +/** + * Registers the observer aBackupOperationObserver for getting notifications whether a backup or + * restore operation starts or ends. + * + * @since App-Framework_6.2 + */ +EXPORT_C void CBaBackupSessionWrapper::RegisterBackupOperationObserverL(MBackupOperationObserver& aBackupOperationObserver) + { + if (!iBackupOperationNotifier) + { + iBackupOperationNotifier=CBaBackupOperationNotifier::NewL(*iBackupSession); + } + iBackupOperationNotifier->AddBackupOperationObserverL(aBackupOperationObserver); + } + +/** + * De-registers the observer aBackupOperationObserver for getting notifications whether a backup or + * restore operation starts or ends. + * + * @since App-Framework_6.2 + */ +EXPORT_C void CBaBackupSessionWrapper::DeRegisterBackupOperationObserver(MBackupOperationObserver& aBackupOperationObserver) + { + if (iBackupOperationNotifier) + { + iBackupOperationNotifier->RemoveBackupOperationObserver(aBackupOperationObserver); + } + } + +/** + * Returns ETrue when either a backup or restore operation is running, otherwise it retunrs EFalse. + * + * @since App-Framework_6.2 + */ +EXPORT_C TBool CBaBackupSessionWrapper::IsBackupOperationRunning() const + { + return iBackupSession->IsBackupOperationRunning(); + } + +/** + * Notifies the server that a backup operation is going to happen. + * + * @since App-Framework_6.2 + * @publishedPartner + * @released + * @capability WriteDeviceData + */ +EXPORT_C void CBaBackupSessionWrapper::NotifyBackupOperationL(const TBackupOperationAttributes& aBackupOperationAttributes) + { + iBackupSession->NotifyBackupOperation(aBackupOperationAttributes); + } + + +EXPORT_C void MBackupOperationObserver::Reserved1() + { + }