--- a/smsprotocols/smsstack/smsprot/Src/smspmondsk.cpp Mon May 03 13:37:20 2010 +0300
+++ b/smsprotocols/smsstack/smsprot/Src/smspmondsk.cpp Thu May 06 15:10:38 2010 +0100
@@ -1,593 +1,593 @@
-// Copyright (c) 1999-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:
-// Implementation for a CActive based class that monitors for low disk space
-// and is informed when a PDU is being received. Should memory be too low,
-// an error code is returned causing a NAck. The class will then monitor
-// for the point at which PDUs can be received again, and a Resume Reception
-// will be sent to the network.
-// The are two limits - a high limit for general SMSs and a low limit for
-// class 0 SMSs. However there is only one way to resume reception of SMSs. So
-// once a resume reception is sent, it resumes hoth types of SMSs. The algorithm
-// is a bit simiplier because of this:
-// IF sending non-Class 0 AND we are below the high limit THEN
-// N'Ack SMS
-// IF not waiting for free diskspace THEN
-// Wait for free diskspace to rise above the high limit
-// Resume SMS Reception.
-// ELSE
-// Continue waiting for either high limit or low limit
-// Resume SMS Reception as previously intended
-// END_IF
-// ELSE IF sending Class 0 AND we are below the low limit THEN
-// Wait for free diskspace to rise above the low limit
-// Resume SMS Reception.
-// END_IF
-// Note that in the second and last case, SMS reception may be resumed before
-// we are above the high limit, but in that case montioring will repeat when
-// the next non-class 0 SMS is attempted to be delivered. This is necessary as
-// there is no way to resume just class 0 SMSs.
-//
-//
-
-/**
- @file
- @internalComponent
-*/
-
-#include <barsc.h>
-#include <bautils.h>
-
-#include "smspcomm.h"
-#include "smspmondsk.h"
-#include "smsstacklog.h"
-#include "smspmain.h"
-#include "smspver.h"
-#include <smsu.rsg>
-
-
-_LIT(KSmsResourceFile, "sms\\smsu.rsc");
-
-
-/**
- * 2 phase constructor.
- *
- * @leave Leaves if not enough memory is available.
- *
- * @return a newly created CSmsMonitorDiskSpace object.
- */
-CSmsMonitorDiskSpace* CSmsMonitorDiskSpace::NewL(MSmsComm& aSmsComm, RMobileSmsMessaging& aSmsMessaging,RFs& aFs)
- {
- LOGSMSPROT1("CSmsMonitorDiskSpace::NewL()");
-
- CSmsMonitorDiskSpace* self = new(ELeave) CSmsMonitorDiskSpace(aSmsComm, aSmsMessaging, aFs);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
-
- return self;
- } // CSmsMonitorDiskSpace::NewL
-
-
-/**
- * Private constructor used in the first phase of construction.
- */
-CSmsMonitorDiskSpace::CSmsMonitorDiskSpace(MSmsComm& aSmsComm, RMobileSmsMessaging& aSmsMessaging,RFs& aFs)
- : CActive(KSmsSessionPriority),
- iState(ESmsMonitorDiskSpaceIdle),
- iSmsMessaging(aSmsMessaging),
- iFs(aFs),
- iSmsComm(aSmsComm),
- iLowLimit(8*1024),
- iHighLimit(16*1024)
- {
- CActiveScheduler::Add(this);
- } // CSmsMonitorDiskSpace::CSmsMonitorDiskSpace
-
-
-/**
- * Destructor. Ensures any outstanding operation is cancelled.
- */
-CSmsMonitorDiskSpace::~CSmsMonitorDiskSpace()
- {
- Cancel();
-
-#ifdef _DEBUG
- iFreeDiskSpaceProperty.Close();
-#endif
-
- } // CSmsMonitorDiskSpace::~CSmsMonitorDiskSpace
-
-
-/**
- * Initialize values for LowLimitDiskSpace and HighLimitDiskSpace
- * from resource file
- */
-void CSmsMonitorDiskSpace::ConstructL()
- {
- RResourceFile resourceFile;
- TFileName fileName;
- Dll::FileName(fileName);
- TParse parse;
- TFileName resourceFileName;
-
- //
- // Create the path to the resource file...
- //
- iFs.PrivatePath(resourceFileName);
- resourceFileName.Append(KSmsResourceFile);
- parse.Set(resourceFileName, &fileName, 0);
- fileName = parse.FullName();
- BaflUtils::NearestLanguageFile(iFs, fileName);
-
- //
- // To enable adequate CSmsMonitorDiskSpace testing we allow the SMSU.RSC
- // file to be loaded from the C: drive if it exists. This is only for a
- // DEBUG version of course! Later WINSCW is also added to allow the testing
- // on WINSCW UREL version.
- //
-#if (defined __WINSCW__) || (defined _DEBUG)
- TUint attValue;
- TChar oldDriveLetter = fileName[0];
-
- //
- // Change the filename to look on C: and then see if it exists...
- //
- fileName[0] = 'C';
-
- if (iFs.Att(fileName, attValue) != KErrNone)
- {
- //
- // The file does not exist on C: so revert the change...
- //
- fileName[0] = oldDriveLetter;
- }
-#endif
-
- //
- // Log the filename in use and whether it is ROM based...
- //
-#ifdef _SMS_LOGGING_ENABLED
- TBuf8<KMaxFileName> buf8;
- buf8.Copy(fileName);
- LOGSMSPROT2("CSmsMonitorDiskSpace::ConstructL(): fileName=\"%S\"", &buf8);
-#endif
-
- if (iFs.IsFileInRom(fileName) == NULL)
- {
- LOGSMSPROT1("CSmsMonitorDiskSpace::ConstructL(): Smsu.rsc not in ROM");
- }
-
- //
- // Read the low and high limits...
- //
- TResourceReader reader;
- HBufC8* buf;
-
- resourceFile.OpenL(iFs, fileName);
- CleanupClosePushL(resourceFile);
-
- buf = resourceFile.AllocReadLC(R_LOWLIMIT_DISKSPACE_HOLDER);
- reader.SetBuffer(buf);
- iLowLimit = reader.ReadInt32();
- CleanupStack::PopAndDestroy(buf);
-
- buf = resourceFile.AllocReadLC(R_HIGHLIMIT_DISKSPACE_HOLDER);
- reader.SetBuffer(buf);
- iHighLimit=reader.ReadInt32();
- CleanupStack::PopAndDestroy(buf);
-
- CleanupStack::PopAndDestroy(&resourceFile);
-
-#ifdef _DEBUG
- TInt freeSpace;
- TInt err = RProperty::Get(KUidPSSMSStackCategory, KUidPSSMSStackFreeDiskSpaceKey, freeSpace);
- if (err == KErrNone)
- {
- iInOODTesting = ETrue;
-
- TInt ret = iFreeDiskSpaceProperty.Attach(KUidPSSMSStackCategory, KUidPSSMSStackFreeDiskSpaceKey);
- if (ret != KErrNone)
- {
- LOGSMSPROT2("iFreeDiskSpaceProperty.Attach(): error=%d", ret);
- User::Leave(ret);
- }
- }
-#endif
-
- LOGSMSPROT3("CSmsMonitorDiskSpace::ConstructL(): iLowLimit=%d, iHighLimit=%d",
- iLowLimit, iHighLimit);
- } // CSmsMonitorDiskSpace::ConstructL
-
-
-/**
- * Handles a completed disk monitor or resume request.
- */
-void CSmsMonitorDiskSpace::RunL()
- {
- LOGSMSPROT3("CSmsMonitorDiskSpace:RunL(): iStatus=%d, iState=%d",
- iStatus.Int(), iState );
-
- switch (iState)
- {
- case ESmsMonitorDiskSpaceMonitorLowLimit:
- {
- iState = ESmsMonitorDiskSpaceIdle;
-
- //
- // If the disk space has gone above the low limit, then
- // resume reception. Otherwise (assuming the notify was
- // successful) then start monitoring the low limit again...
- //
- TInt freeDiskSpace = GetFreeDiskSpace();
-
- if (freeDiskSpace >= iLowLimit)
- {
- ResumeSmsReception();
- }
- else if (iStatus.Int() == KErrNone)
- {
- NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
- }
- }
- break;
-
- case ESmsMonitorDiskSpaceMonitorHighLimit:
- {
- iState = ESmsMonitorDiskSpaceIdle;
-
- //
- // If the disk space has gone above the high limit, then
- // resume reception. Otherwise (assuming the notify was
- // successful) then start monitoring the high limit again...
- //
- TInt freeDiskSpace = GetFreeDiskSpace();
-
- if (freeDiskSpace >= iHighLimit)
- {
- ResumeSmsReception();
- }
- else if (iStatus.Int() == KErrNone)
- {
- NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
- }
- }
- break;
-
- case ESmsMonitorDiskSpaceResumeReception:
- {
- //
- // We are finished. However, check if any N'Acks were sent between
- // the time we began the resume and now incase we need to restart
- // the monitoring.
- //
- if (iNAckdClassZero)
- {
- NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
- }
- else if (iNAckdClassOther)
- {
- NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
- }
- else
- {
- iState = ESmsMonitorDiskSpaceIdle;
- }
- }
- break;
-
- default:
- {
- SmspPanic(KSmspPanicUnexpectedState);
- }
- break;
- }
- } // CSmsMonitorDiskSpace::RunL
-
-
-/**
- * Handles a request to cancel the current state machine operation.
- */
-void CSmsMonitorDiskSpace::DoCancel()
- {
- LOGSMSPROT2("CSmsMonitorDiskSpace::DoCancel(): iState=%d", iState);
-
- switch (iState)
- {
- case ESmsMonitorDiskSpaceIdle:
- {
- // NOP
- }
- break;
-
- case ESmsMonitorDiskSpaceMonitorLowLimit:
- case ESmsMonitorDiskSpaceMonitorHighLimit:
- {
-#ifdef _DEBUG
- if (iInOODTesting)
- {
- iFreeDiskSpaceProperty.Cancel();
- }
- else
-#endif
- {
- iFs.NotifyDiskSpaceCancel();
- }
-
- }
- break;
-
- case ESmsMonitorDiskSpaceResumeReception:
- {
- iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingResumeSmsReception);
- }
- break;
-
- default:
- {
- SmspPanic(KSmspPanicUnexpectedState);
- }
- }
-
- iState = ESmsMonitorDiskSpaceIdle;
- } // CSmsMonitorDiskSpace::DoCancel
-
-
-/**
- * Checks for enough disk space, and starts monitoring disk space if needed.
- */
-void CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL(TBool aPDUIsClass0)
- {
- LOGSMSPROT2("CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL(): aPDUIsClass0=%d",
- aPDUIsClass0);
-
- //
- // First check the actual disk space before working out what to do.
- //
- // If enough space exists, then we don't need to do anything else (even if
- // we where previously monitoring, because that will be handled later as
- // it would without this function call).
- //
- TInt freeDiskSpace = GetFreeDiskSpace();
-
- if (freeDiskSpace >= iHighLimit ||
- (freeDiskSpace >= iLowLimit && aPDUIsClass0))
- {
- //
- // There is enough space for the PDU, so nothing more to do.
- //
- return;
- }
-
- //
- // There is not enough diskspace so record that a PDU will be N'Ack'd.
- //
- if (aPDUIsClass0)
- {
- iNAckdClassZero = ETrue;
- }
- else
- {
- iNAckdClassOther = ETrue;
- }
-
- //
- // Ensure we are monitoring the disk space. This will then cause a
- // ResumeReception() to be sent when the disk space increases above the
- // appropriate limit.
- //
- if (freeDiskSpace < iLowLimit)
- {
- //
- // Start montioring the low limit, if not already monitoring or if
- // we are currently monitoring the high limit.
- //
- if (iState == ESmsMonitorDiskSpaceIdle ||
- iState == ESmsMonitorDiskSpaceMonitorHighLimit)
- {
- NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
- }
- }
- else // (freeDiskSpace < iHighLimit)
- {
- //
- // Start monitoring the high limit if not already monitoring...
- //
- if (iState == ESmsMonitorDiskSpaceIdle)
- {
- NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
- }
- }
-
- //
- // Imform the caller that the SMS should be N'Ack'd...
- //
- User::Leave(KErrDiskFull);
- } // CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL
-
-
-/**
- * Starts monitoring the free disk space to spot when it rises above the
- * requested limit.
- *
- * Unfortunately the File System API does not distiguish between going below
- * or above a limit, so some checking is needed to ensure that the correct
- * behaviour is requested, since it is possible in theory for the disk space
- * to change between the calls.
- *
- * In theory this is unlikely since the priority of the SMS Stack is higher
- * but not impossible to happen. We guard against it anyway since the mere
- * fact it could happen poses questions when the defects come in from handsets.
- *
- * @note The current disk space is assumed to be below the limit requested.
- * If it is found to be above, this will cause an imediate completion.
- *
- * @param aLimit Limit to monitor.
- * @param aState State to transition to when this request is made.
- */
-void CSmsMonitorDiskSpace::NotifyDiskSpace(TInt aLimit,
- TSmsMonitorDiskSpaceState aState)
- {
- LOGSMSPROT3("CSmsMonitorDiskSpace::NotifyDiskSpace(): aLimit=%d, aState=%d",
- aLimit, aState);
-
- //
- // Cancel any previously outstanding requests...
- //
- if (iState != ESmsMonitorDiskSpaceIdle)
- {
- Cancel();
- }
-
- //
- // Start the notification...
- //
- iState = aState;
-
-#ifdef _DEBUG
- if (iInOODTesting)
- {
- iFreeDiskSpaceProperty.Subscribe(iStatus);
- }
- else
-#endif
- {
- iFs.NotifyDiskSpace(aLimit, EDriveC, iStatus);
- }
-
- iSmsComm.DiskSpaceMonitorStateChange(ESmsDiskSpaceFull);
- SetActive();
-
- //
- // Now, as a sanity check, check the diskspace again. If the disk space
- // has advanced above the limit in the time between the request and now,
- // or since the last call to GetFreeDiskSpace() then the request will
- // either be invalid, or have completed. If either of these are the case
- // we need to control the situation and ensure a completion occurs...
- //
- TInt freeDiskSpace = GetFreeDiskSpace();
-
- if (freeDiskSpace > aLimit)
- {
- //
- // Cancel the request...
- //
- Cancel();
-
- //
- // Force a fake completion for this state...
- //
- TRequestStatus* status = &iStatus;
-
- iState = aState;
- iStatus = KRequestPending;
- SetActive();
- User::RequestComplete(status, KErrNone);
- }
- } // CSmsMonitorDiskSpace::NotifyDiskSpace
-
-
-/**
- * Performs the required actions for the case when leaving either the low
- * limit or the high limit. It doesn't really matter which limit you are
- * leaving since the resume applies for all SMSs. This gives three scenarios:
- *
- * 1) You leave the high limit. This is not a problem as all SMSs can
- * now be received.
- * 2) You leave the low limit and go above the high limit. This is also
- * not a problem as all SMSs can be received.
- * 3) You leave the low limit but stay below the high limit. In this case
- * the N'Ack'd SMS was class 0 and you can now receive it. A non-class 0
- * SMS may attempt to be delivered, but monitoring will restart as
- * before. So again no problem.
- */
-void CSmsMonitorDiskSpace::ResumeSmsReception()
- {
- LOGSMSPROT1("CSmsMonitorDiskSpace::ResumeSmsReception");
-
- //
- // Cancel any previously outstanding requests...
- //
- if (iState != ESmsMonitorDiskSpaceIdle)
- {
- Cancel();
- }
-
- //
- // Clear the N'Ackd flags...
- //
- iNAckdClassZero = EFalse;
- iNAckdClassOther = EFalse;
-
- //
- // Start the resume request...
- //
- iState = ESmsMonitorDiskSpaceResumeReception;
- iSmsMessaging.ResumeSmsReception(iStatus);
- iSmsComm.DiskSpaceMonitorStateChange(ESmsDiskSpaceAvailable);
- SetActive();
- } // CSmsMonitorDiskSpace::ResumeSmsReception
-
-
-/**
- * Utilility function to determine amount of free disk space. The actual
- * free space is limited at 2GB.
- */
-TInt CSmsMonitorDiskSpace::GetFreeDiskSpace()
- {
- TVolumeInfo volumeInfo;
- TInt ret;
-
-#ifdef _DEBUG
- if( iInOODTesting )
- {
- TInt value = 0;
- ret = iFreeDiskSpaceProperty.Get(value);
-
- // update volumeInfo with value regardless of error as error handled later
- volumeInfo.iFree = value;
- }
- else
-#endif
- {
- ret = iFs.Volume(volumeInfo, EDriveC);
- }
-
- //
- // Get the volume info for drive C:...
- //
-
- if (ret != KErrNone)
- {
- LOGSMSPROT2("CSmsMonitorDiskSpace::GetFreeDiskSpace(): error=%d", ret);
- return KErrGeneral;
- }
-
- //
- // Convert the disk space value to a TInt (allowing 2GB limits)...
- //
- TInt freeSpace;
-
- if (volumeInfo.iFree >= 0x7fffffff)
- {
- freeSpace = 0x7fffffff;
- }
- else
- {
- freeSpace = (TInt) volumeInfo.iFree;
- }
-
- LOGSMSPROT2("CSmsMonitorDiskSpace::GetFreeDiskSpace(): freeSpace=%d", freeSpace);
-
- return freeSpace;
- } // CSmsMonitorDiskSpace::GetFreeDiskSpace
+// Copyright (c) 1999-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:
+// Implementation for a CActive based class that monitors for low disk space
+// and is informed when a PDU is being received. Should memory be too low,
+// an error code is returned causing a NAck. The class will then monitor
+// for the point at which PDUs can be received again, and a Resume Reception
+// will be sent to the network.
+// The are two limits - a high limit for general SMSs and a low limit for
+// class 0 SMSs. However there is only one way to resume reception of SMSs. So
+// once a resume reception is sent, it resumes hoth types of SMSs. The algorithm
+// is a bit simiplier because of this:
+// IF sending non-Class 0 AND we are below the high limit THEN
+// N'Ack SMS
+// IF not waiting for free diskspace THEN
+// Wait for free diskspace to rise above the high limit
+// Resume SMS Reception.
+// ELSE
+// Continue waiting for either high limit or low limit
+// Resume SMS Reception as previously intended
+// END_IF
+// ELSE IF sending Class 0 AND we are below the low limit THEN
+// Wait for free diskspace to rise above the low limit
+// Resume SMS Reception.
+// END_IF
+// Note that in the second and last case, SMS reception may be resumed before
+// we are above the high limit, but in that case montioring will repeat when
+// the next non-class 0 SMS is attempted to be delivered. This is necessary as
+// there is no way to resume just class 0 SMSs.
+//
+//
+
+/**
+ @file
+ @internalComponent
+*/
+
+#include <barsc.h>
+#include <bautils.h>
+
+#include "smspcomm.h"
+#include "smspmondsk.h"
+#include "smsstacklog.h"
+#include "smspmain.h"
+#include "smspver.h"
+#include <smsu.rsg>
+
+
+_LIT(KSmsResourceFile, "sms\\smsu.rsc");
+
+
+/**
+ * 2 phase constructor.
+ *
+ * @leave Leaves if not enough memory is available.
+ *
+ * @return a newly created CSmsMonitorDiskSpace object.
+ */
+CSmsMonitorDiskSpace* CSmsMonitorDiskSpace::NewL(MSmsComm& aSmsComm, RMobileSmsMessaging& aSmsMessaging,RFs& aFs)
+ {
+ LOGSMSPROT1("CSmsMonitorDiskSpace::NewL()");
+
+ CSmsMonitorDiskSpace* self = new(ELeave) CSmsMonitorDiskSpace(aSmsComm, aSmsMessaging, aFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ return self;
+ } // CSmsMonitorDiskSpace::NewL
+
+
+/**
+ * Private constructor used in the first phase of construction.
+ */
+CSmsMonitorDiskSpace::CSmsMonitorDiskSpace(MSmsComm& aSmsComm, RMobileSmsMessaging& aSmsMessaging,RFs& aFs)
+ : CActive(KSmsSessionPriority),
+ iState(ESmsMonitorDiskSpaceIdle),
+ iSmsMessaging(aSmsMessaging),
+ iFs(aFs),
+ iSmsComm(aSmsComm),
+ iLowLimit(8*1024),
+ iHighLimit(16*1024)
+ {
+ CActiveScheduler::Add(this);
+ } // CSmsMonitorDiskSpace::CSmsMonitorDiskSpace
+
+
+/**
+ * Destructor. Ensures any outstanding operation is cancelled.
+ */
+CSmsMonitorDiskSpace::~CSmsMonitorDiskSpace()
+ {
+ Cancel();
+
+#ifdef _DEBUG
+ iFreeDiskSpaceProperty.Close();
+#endif
+
+ } // CSmsMonitorDiskSpace::~CSmsMonitorDiskSpace
+
+
+/**
+ * Initialize values for LowLimitDiskSpace and HighLimitDiskSpace
+ * from resource file
+ */
+void CSmsMonitorDiskSpace::ConstructL()
+ {
+ RResourceFile resourceFile;
+ TFileName fileName;
+ Dll::FileName(fileName);
+ TParse parse;
+ TFileName resourceFileName;
+
+ //
+ // Create the path to the resource file...
+ //
+ iFs.PrivatePath(resourceFileName);
+ resourceFileName.Append(KSmsResourceFile);
+ parse.Set(resourceFileName, &fileName, 0);
+ fileName = parse.FullName();
+ BaflUtils::NearestLanguageFile(iFs, fileName);
+
+ //
+ // To enable adequate CSmsMonitorDiskSpace testing we allow the SMSU.RSC
+ // file to be loaded from the C: drive if it exists. This is only for a
+ // DEBUG version of course! Later WINSCW is also added to allow the testing
+ // on WINSCW UREL version.
+ //
+#if (defined __WINSCW__) || (defined _DEBUG)
+ TUint attValue;
+ TChar oldDriveLetter = fileName[0];
+
+ //
+ // Change the filename to look on C: and then see if it exists...
+ //
+ fileName[0] = 'C';
+
+ if (iFs.Att(fileName, attValue) != KErrNone)
+ {
+ //
+ // The file does not exist on C: so revert the change...
+ //
+ fileName[0] = oldDriveLetter;
+ }
+#endif
+
+ //
+ // Log the filename in use and whether it is ROM based...
+ //
+#ifdef _SMS_LOGGING_ENABLED
+ TBuf8<KMaxFileName> buf8;
+ buf8.Copy(fileName);
+ LOGSMSPROT2("CSmsMonitorDiskSpace::ConstructL(): fileName=\"%S\"", &buf8);
+#endif
+
+ if (iFs.IsFileInRom(fileName) == NULL)
+ {
+ LOGSMSPROT1("CSmsMonitorDiskSpace::ConstructL(): Smsu.rsc not in ROM");
+ }
+
+ //
+ // Read the low and high limits...
+ //
+ TResourceReader reader;
+ HBufC8* buf;
+
+ resourceFile.OpenL(iFs, fileName);
+ CleanupClosePushL(resourceFile);
+
+ buf = resourceFile.AllocReadLC(R_LOWLIMIT_DISKSPACE_HOLDER);
+ reader.SetBuffer(buf);
+ iLowLimit = reader.ReadInt32();
+ CleanupStack::PopAndDestroy(buf);
+
+ buf = resourceFile.AllocReadLC(R_HIGHLIMIT_DISKSPACE_HOLDER);
+ reader.SetBuffer(buf);
+ iHighLimit=reader.ReadInt32();
+ CleanupStack::PopAndDestroy(buf);
+
+ CleanupStack::PopAndDestroy(&resourceFile);
+
+#ifdef _DEBUG
+ TInt freeSpace;
+ TInt err = RProperty::Get(KUidPSSMSStackCategory, KUidPSSMSStackFreeDiskSpaceKey, freeSpace);
+ if (err == KErrNone)
+ {
+ iInOODTesting = ETrue;
+
+ TInt ret = iFreeDiskSpaceProperty.Attach(KUidPSSMSStackCategory, KUidPSSMSStackFreeDiskSpaceKey);
+ if (ret != KErrNone)
+ {
+ LOGSMSPROT2("iFreeDiskSpaceProperty.Attach(): error=%d", ret);
+ User::Leave(ret);
+ }
+ }
+#endif
+
+ LOGSMSPROT3("CSmsMonitorDiskSpace::ConstructL(): iLowLimit=%d, iHighLimit=%d",
+ iLowLimit, iHighLimit);
+ } // CSmsMonitorDiskSpace::ConstructL
+
+
+/**
+ * Handles a completed disk monitor or resume request.
+ */
+void CSmsMonitorDiskSpace::RunL()
+ {
+ LOGSMSPROT3("CSmsMonitorDiskSpace:RunL(): iStatus=%d, iState=%d",
+ iStatus.Int(), iState );
+
+ switch (iState)
+ {
+ case ESmsMonitorDiskSpaceMonitorLowLimit:
+ {
+ iState = ESmsMonitorDiskSpaceIdle;
+
+ //
+ // If the disk space has gone above the low limit, then
+ // resume reception. Otherwise (assuming the notify was
+ // successful) then start monitoring the low limit again...
+ //
+ TInt freeDiskSpace = GetFreeDiskSpace();
+
+ if (freeDiskSpace >= iLowLimit)
+ {
+ ResumeSmsReception();
+ }
+ else if (iStatus.Int() == KErrNone)
+ {
+ NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
+ }
+ }
+ break;
+
+ case ESmsMonitorDiskSpaceMonitorHighLimit:
+ {
+ iState = ESmsMonitorDiskSpaceIdle;
+
+ //
+ // If the disk space has gone above the high limit, then
+ // resume reception. Otherwise (assuming the notify was
+ // successful) then start monitoring the high limit again...
+ //
+ TInt freeDiskSpace = GetFreeDiskSpace();
+
+ if (freeDiskSpace >= iHighLimit)
+ {
+ ResumeSmsReception();
+ }
+ else if (iStatus.Int() == KErrNone)
+ {
+ NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
+ }
+ }
+ break;
+
+ case ESmsMonitorDiskSpaceResumeReception:
+ {
+ //
+ // We are finished. However, check if any N'Acks were sent between
+ // the time we began the resume and now incase we need to restart
+ // the monitoring.
+ //
+ if (iNAckdClassZero)
+ {
+ NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
+ }
+ else if (iNAckdClassOther)
+ {
+ NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
+ }
+ else
+ {
+ iState = ESmsMonitorDiskSpaceIdle;
+ }
+ }
+ break;
+
+ default:
+ {
+ SmspPanic(KSmspPanicUnexpectedState);
+ }
+ break;
+ }
+ } // CSmsMonitorDiskSpace::RunL
+
+
+/**
+ * Handles a request to cancel the current state machine operation.
+ */
+void CSmsMonitorDiskSpace::DoCancel()
+ {
+ LOGSMSPROT2("CSmsMonitorDiskSpace::DoCancel(): iState=%d", iState);
+
+ switch (iState)
+ {
+ case ESmsMonitorDiskSpaceIdle:
+ {
+ // NOP
+ }
+ break;
+
+ case ESmsMonitorDiskSpaceMonitorLowLimit:
+ case ESmsMonitorDiskSpaceMonitorHighLimit:
+ {
+#ifdef _DEBUG
+ if (iInOODTesting)
+ {
+ iFreeDiskSpaceProperty.Cancel();
+ }
+ else
+#endif
+ {
+ iFs.NotifyDiskSpaceCancel();
+ }
+
+ }
+ break;
+
+ case ESmsMonitorDiskSpaceResumeReception:
+ {
+ iSmsMessaging.CancelAsyncRequest(EMobileSmsMessagingResumeSmsReception);
+ }
+ break;
+
+ default:
+ {
+ SmspPanic(KSmspPanicUnexpectedState);
+ }
+ }
+
+ iState = ESmsMonitorDiskSpaceIdle;
+ } // CSmsMonitorDiskSpace::DoCancel
+
+
+/**
+ * Checks for enough disk space, and starts monitoring disk space if needed.
+ */
+void CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL(TBool aPDUIsClass0)
+ {
+ LOGSMSPROT2("CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL(): aPDUIsClass0=%d",
+ aPDUIsClass0);
+
+ //
+ // First check the actual disk space before working out what to do.
+ //
+ // If enough space exists, then we don't need to do anything else (even if
+ // we where previously monitoring, because that will be handled later as
+ // it would without this function call).
+ //
+ TInt freeDiskSpace = GetFreeDiskSpace();
+
+ if (freeDiskSpace >= iHighLimit ||
+ (freeDiskSpace >= iLowLimit && aPDUIsClass0))
+ {
+ //
+ // There is enough space for the PDU, so nothing more to do.
+ //
+ return;
+ }
+
+ //
+ // There is not enough diskspace so record that a PDU will be N'Ack'd.
+ //
+ if (aPDUIsClass0)
+ {
+ iNAckdClassZero = ETrue;
+ }
+ else
+ {
+ iNAckdClassOther = ETrue;
+ }
+
+ //
+ // Ensure we are monitoring the disk space. This will then cause a
+ // ResumeReception() to be sent when the disk space increases above the
+ // appropriate limit.
+ //
+ if (freeDiskSpace < iLowLimit)
+ {
+ //
+ // Start montioring the low limit, if not already monitoring or if
+ // we are currently monitoring the high limit.
+ //
+ if (iState == ESmsMonitorDiskSpaceIdle ||
+ iState == ESmsMonitorDiskSpaceMonitorHighLimit)
+ {
+ NotifyDiskSpace(iLowLimit, ESmsMonitorDiskSpaceMonitorLowLimit);
+ }
+ }
+ else // (freeDiskSpace < iHighLimit)
+ {
+ //
+ // Start monitoring the high limit if not already monitoring...
+ //
+ if (iState == ESmsMonitorDiskSpaceIdle)
+ {
+ NotifyDiskSpace(iHighLimit, ESmsMonitorDiskSpaceMonitorHighLimit);
+ }
+ }
+
+ //
+ // Imform the caller that the SMS should be N'Ack'd...
+ //
+ User::Leave(KErrDiskFull);
+ } // CSmsMonitorDiskSpace::CheckDiskSpaceForPDUL
+
+
+/**
+ * Starts monitoring the free disk space to spot when it rises above the
+ * requested limit.
+ *
+ * Unfortunately the File System API does not distiguish between going below
+ * or above a limit, so some checking is needed to ensure that the correct
+ * behaviour is requested, since it is possible in theory for the disk space
+ * to change between the calls.
+ *
+ * In theory this is unlikely since the priority of the SMS Stack is higher
+ * but not impossible to happen. We guard against it anyway since the mere
+ * fact it could happen poses questions when the defects come in from handsets.
+ *
+ * @note The current disk space is assumed to be below the limit requested.
+ * If it is found to be above, this will cause an imediate completion.
+ *
+ * @param aLimit Limit to monitor.
+ * @param aState State to transition to when this request is made.
+ */
+void CSmsMonitorDiskSpace::NotifyDiskSpace(TInt aLimit,
+ TSmsMonitorDiskSpaceState aState)
+ {
+ LOGSMSPROT3("CSmsMonitorDiskSpace::NotifyDiskSpace(): aLimit=%d, aState=%d",
+ aLimit, aState);
+
+ //
+ // Cancel any previously outstanding requests...
+ //
+ if (iState != ESmsMonitorDiskSpaceIdle)
+ {
+ Cancel();
+ }
+
+ //
+ // Start the notification...
+ //
+ iState = aState;
+
+#ifdef _DEBUG
+ if (iInOODTesting)
+ {
+ iFreeDiskSpaceProperty.Subscribe(iStatus);
+ }
+ else
+#endif
+ {
+ iFs.NotifyDiskSpace(aLimit, EDriveC, iStatus);
+ }
+
+ iSmsComm.DiskSpaceMonitorStateChange(ESmsDiskSpaceFull);
+ SetActive();
+
+ //
+ // Now, as a sanity check, check the diskspace again. If the disk space
+ // has advanced above the limit in the time between the request and now,
+ // or since the last call to GetFreeDiskSpace() then the request will
+ // either be invalid, or have completed. If either of these are the case
+ // we need to control the situation and ensure a completion occurs...
+ //
+ TInt freeDiskSpace = GetFreeDiskSpace();
+
+ if (freeDiskSpace > aLimit)
+ {
+ //
+ // Cancel the request...
+ //
+ Cancel();
+
+ //
+ // Force a fake completion for this state...
+ //
+ TRequestStatus* status = &iStatus;
+
+ iState = aState;
+ iStatus = KRequestPending;
+ SetActive();
+ User::RequestComplete(status, KErrNone);
+ }
+ } // CSmsMonitorDiskSpace::NotifyDiskSpace
+
+
+/**
+ * Performs the required actions for the case when leaving either the low
+ * limit or the high limit. It doesn't really matter which limit you are
+ * leaving since the resume applies for all SMSs. This gives three scenarios:
+ *
+ * 1) You leave the high limit. This is not a problem as all SMSs can
+ * now be received.
+ * 2) You leave the low limit and go above the high limit. This is also
+ * not a problem as all SMSs can be received.
+ * 3) You leave the low limit but stay below the high limit. In this case
+ * the N'Ack'd SMS was class 0 and you can now receive it. A non-class 0
+ * SMS may attempt to be delivered, but monitoring will restart as
+ * before. So again no problem.
+ */
+void CSmsMonitorDiskSpace::ResumeSmsReception()
+ {
+ LOGSMSPROT1("CSmsMonitorDiskSpace::ResumeSmsReception");
+
+ //
+ // Cancel any previously outstanding requests...
+ //
+ if (iState != ESmsMonitorDiskSpaceIdle)
+ {
+ Cancel();
+ }
+
+ //
+ // Clear the N'Ackd flags...
+ //
+ iNAckdClassZero = EFalse;
+ iNAckdClassOther = EFalse;
+
+ //
+ // Start the resume request...
+ //
+ iState = ESmsMonitorDiskSpaceResumeReception;
+ iSmsMessaging.ResumeSmsReception(iStatus);
+ iSmsComm.DiskSpaceMonitorStateChange(ESmsDiskSpaceAvailable);
+ SetActive();
+ } // CSmsMonitorDiskSpace::ResumeSmsReception
+
+
+/**
+ * Utilility function to determine amount of free disk space. The actual
+ * free space is limited at 2GB.
+ */
+TInt CSmsMonitorDiskSpace::GetFreeDiskSpace()
+ {
+ TVolumeInfo volumeInfo;
+ TInt ret;
+
+#ifdef _DEBUG
+ if( iInOODTesting )
+ {
+ TInt value = 0;
+ ret = iFreeDiskSpaceProperty.Get(value);
+
+ // update volumeInfo with value regardless of error as error handled later
+ volumeInfo.iFree = value;
+ }
+ else
+#endif
+ {
+ ret = iFs.Volume(volumeInfo, EDriveC);
+ }
+
+ //
+ // Get the volume info for drive C:...
+ //
+
+ if (ret != KErrNone)
+ {
+ LOGSMSPROT2("CSmsMonitorDiskSpace::GetFreeDiskSpace(): error=%d", ret);
+ return KErrGeneral;
+ }
+
+ //
+ // Convert the disk space value to a TInt (allowing 2GB limits)...
+ //
+ TInt freeSpace;
+
+ if (volumeInfo.iFree >= 0x7fffffff)
+ {
+ freeSpace = 0x7fffffff;
+ }
+ else
+ {
+ freeSpace = (TInt) volumeInfo.iFree;
+ }
+
+ LOGSMSPROT2("CSmsMonitorDiskSpace::GetFreeDiskSpace(): freeSpace=%d", freeSpace);
+
+ return freeSpace;
+ } // CSmsMonitorDiskSpace::GetFreeDiskSpace