installationservices/swinstallationfw/source/sifnotification.cpp
branchRCL_3
changeset 25 7333d7932ef7
equal deleted inserted replaced
24:5cc91383ab1e 25:7333d7932ef7
       
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * This file implements the SifNotifier library
       
    16 *
       
    17 */
       
    18 
       
    19 #include <usif/sif/sifnotification.h>
       
    20 #include <s32mem.h> 
       
    21 #include <scs/cleanuputils.h>
       
    22 #include <scs/streamingarray.h>
       
    23 #include "sifnotification_internal.h"
       
    24 #include <usif/sif/sif.h>
       
    25 #include "e32property.h" 
       
    26 #include "scrclient.inl"
       
    27 #include "usiflog.h"
       
    28 
       
    29 
       
    30 using namespace Usif;
       
    31 
       
    32 /**
       
    33  * A global method which is used by both the publisher and subscriber code to retrieve data.
       
    34  * 
       
    35  */
       
    36 void GetDataL(TUint aKey, TInt& aBufferSize, RBuf8& aData)
       
    37     {
       
    38     aData.CreateL(aBufferSize);
       
    39     aData.CleanupClosePushL();
       
    40     TInt err = RProperty::Get(KUidSystemCategory, aKey, aData);
       
    41     
       
    42     // If the buffer size is too small.
       
    43     while (err == KErrOverflow)
       
    44         {
       
    45         aBufferSize*=2;
       
    46         aData.ReAllocL(aBufferSize);
       
    47         err = RProperty::Get(KUidSystemCategory, aKey, aData);
       
    48         }
       
    49         
       
    50     User::LeaveIfError(err);
       
    51     CleanupStack::Pop();
       
    52     }
       
    53 
       
    54 ////////////////////////////
       
    55 // CPublishSifOperationInfo
       
    56 ////////////////////////////
       
    57 
       
    58 CPublishSifOperationInfo::CPublishSifOperationInfo():
       
    59     iBufferSize(KBufferSize)
       
    60     {
       
    61     // empty
       
    62     }
       
    63 
       
    64 CPublishSifOperationInfo::~CPublishSifOperationInfo()
       
    65     {
       
    66     delete iDeleteTimer;
       
    67     if (iStartEndKey != 0)
       
    68         {
       
    69         RProperty::Delete(KUidSystemCategory, iStartEndKey);
       
    70         RProperty::Delete(KUidSystemCategory, (iStartEndKey+1));
       
    71         }
       
    72     }
       
    73 
       
    74 EXPORT_C CPublishSifOperationInfo* CPublishSifOperationInfo::NewL()
       
    75     {
       
    76     CPublishSifOperationInfo *self = CPublishSifOperationInfo::NewLC();
       
    77     CleanupStack::Pop(self);
       
    78     return self;
       
    79     }
       
    80 
       
    81 EXPORT_C CPublishSifOperationInfo* CPublishSifOperationInfo::NewLC()
       
    82     {
       
    83     CPublishSifOperationInfo *self = new(ELeave) CPublishSifOperationInfo();
       
    84     CleanupStack::PushL(self);
       
    85     self->ConstructL();
       
    86     return self;
       
    87     }
       
    88 
       
    89 void CPublishSifOperationInfo::ConstructL()
       
    90     {
       
    91     
       
    92     }
       
    93 
       
    94 TUint CPublishSifOperationInfo::AvailableKeyL()
       
    95     {
       
    96     TBuf8<KMaxNumberOfOperations*sizeof(TInt)> buf;
       
    97     for(TInt i=0; i< KMaxNumberOfOperations-1; ++i)
       
    98         {
       
    99         if(KErrNotFound == RProperty::Get(KUidSystemCategory, KSifPropertyTable[i], buf))
       
   100             {
       
   101             return KSifPropertyTable[i];
       
   102             }
       
   103         }
       
   104 
       
   105 	User::Leave(KErrInUse);
       
   106     return KErrNone; // Keep compiler happy.
       
   107     }
       
   108 
       
   109 TUint CPublishSifOperationInfo::KeyForGlobalComponentIdL(const TDesC& aGlobalComponentId)
       
   110     {
       
   111     TBuf8<KMaxNumberOfOperations*sizeof(TInt)> buf;
       
   112     //Get all ongoing operations
       
   113     User::LeaveIfError(RProperty::Get(KUidSystemCategory, KSifOperationKey, buf));
       
   114    
       
   115     RDesReadStream readStream(buf);
       
   116     CleanupClosePushL(readStream);
       
   117     CSifOperationKey* opKey = CSifOperationKey::NewL(readStream);
       
   118     CleanupStack::PopAndDestroy(&readStream);
       
   119     CleanupStack::PushL(opKey);
       
   120     
       
   121     RArray<TUint> startEndKeyArr = opKey->StartEndKeys();
       
   122 	// Get the data for all the ongoing operations and check for global component id
       
   123     for (TInt i=0; i<startEndKeyArr.Count(); ++i)
       
   124         {
       
   125         RBuf8 startDatabuf;
       
   126         startDatabuf.CleanupClosePushL();
       
   127 
       
   128 		GetDataL(startEndKeyArr[i], iBufferSize, startDatabuf);
       
   129         RDesReadStream readStream(startDatabuf);
       
   130         CleanupClosePushL(readStream);
       
   131         
       
   132         // Read the first 4 bytes
       
   133         TSifOperation opType = static_cast<TSifOperation>(readStream.ReadInt32L());         
       
   134         if(opType != ESifOperationStart)
       
   135             {
       
   136             CleanupStack::PopAndDestroy(2, &startDatabuf);
       
   137             continue;
       
   138             }
       
   139                     
       
   140         // Release the stream and reopen it.
       
   141         readStream.Release();
       
   142         readStream.Open(startDatabuf);
       
   143                     
       
   144         CSifOperationStartData* startObj = CSifOperationStartData::NewL(readStream);
       
   145         CleanupStack::PushL(startObj);
       
   146 		// Check if the global component id is the same as what we are looking for
       
   147         if( KErrNone == aGlobalComponentId.Compare(startObj->GlobalComponentId()))
       
   148             {
       
   149             TInt key = startEndKeyArr[i];
       
   150             CleanupStack::PopAndDestroy(4, opKey);
       
   151             return key;
       
   152             }
       
   153         CleanupStack::PopAndDestroy(3, &startDatabuf);
       
   154         }
       
   155     CleanupStack::PopAndDestroy(opKey);
       
   156     
       
   157     // Could not find corresponding key
       
   158     User::Leave(KErrNotFound);
       
   159     return KErrNone; // Keep compiler happy.
       
   160     }
       
   161     
       
   162 void CPublishSifOperationInfo::SetKeyToDelete(TUint aStartEndKey)
       
   163     {
       
   164     iStartEndKey = aStartEndKey;
       
   165     }
       
   166 
       
   167 EXPORT_C void CPublishSifOperationInfo::PublishStartL(CSifOperationStartData& aSifOperationStartData)
       
   168     {
       
   169     // Get Property key from free pool which could be used for this operation.
       
   170     TUint key = AvailableKeyL();    
       
   171     
       
   172     // Define key from free pool. Start data could be bigger than 512 bytes, hence using ELargeByteArray.
       
   173     User::LeaveIfError(RProperty::Define(KUidSystemCategory, key, RProperty::ELargeByteArray,KSecurityPolicyWDD,KSecurityPolicyNone,KStartBufLength));
       
   174         
       
   175     // Store this key and delete it in case of any leaves
       
   176     SetKeyToDelete(key);
       
   177     
       
   178     // Publish start info of operation in defined key.
       
   179     RBuf8 bufStartData;
       
   180     bufStartData.CleanupClosePushL();
       
   181     ExternalizeRefObjectL(aSifOperationStartData, bufStartData);
       
   182 
       
   183     User::LeaveIfError(RProperty::Set(KUidSystemCategory, key, bufStartData));
       
   184     
       
   185     CleanupStack::PopAndDestroy(&bufStartData);
       
   186     
       
   187     // Define key for progress data for this operation.
       
   188     User::LeaveIfError(RProperty::Define(KUidSystemCategory, (key+1), RProperty::EByteArray,KSecurityPolicyWDD,KSecurityPolicyNone, KProgressBufLength));
       
   189     
       
   190     // Publish(append this key to existing info) the newly defined key in the global SIF key.
       
   191     TBuf8<KMaxNumberOfOperations*sizeof(TUint)> buf;
       
   192 
       
   193     User::LeaveIfError(RProperty::Get(KUidSystemCategory, KSifOperationKey, buf));
       
   194 
       
   195     RDesReadStream stream(buf);
       
   196     CleanupClosePushL(stream);      
       
   197     
       
   198     // Retrieve current keys.
       
   199     CSifOperationKey* currentKeys = CSifOperationKey::NewL(stream);
       
   200     CleanupStack::PopAndDestroy(&stream);
       
   201     
       
   202     CleanupStack::PushL(currentKeys);
       
   203     
       
   204     // Append the new key.
       
   205     currentKeys->AddKeyL(key);
       
   206     
       
   207     RBuf8 bufOperationKeys;
       
   208     bufOperationKeys.CleanupClosePushL();
       
   209     ExternalizeRefObjectL(*currentKeys, bufOperationKeys);
       
   210     
       
   211     // Publish the new set of keys.
       
   212     User::LeaveIfError(RProperty::Set(KUidSystemCategory, KSifOperationKey, bufOperationKeys));
       
   213     
       
   214     // Everything finished fine, we need not delete the keys defined above.
       
   215     SetKeyToDelete(0);
       
   216     
       
   217     CleanupStack::PopAndDestroy(2, currentKeys);
       
   218     }
       
   219 
       
   220 EXPORT_C void CPublishSifOperationInfo::PublishProgressL(CSifOperationProgressData& aSifOperationProgressData)
       
   221     {
       
   222     TUint startEndKey = 0;
       
   223     
       
   224     HBufC16 *compGlobalId = aSifOperationProgressData.GlobalComponentId().AllocLC();
       
   225 	//Get the key defined for this operation
       
   226     startEndKey = KeyForGlobalComponentIdL(compGlobalId->Des());
       
   227     CleanupStack::PopAndDestroy(compGlobalId);
       
   228 
       
   229     //Publish progress info of operation in defined key
       
   230     RBuf8 bufProgressData;
       
   231     bufProgressData.CleanupClosePushL();
       
   232     ExternalizeRefObjectL(aSifOperationProgressData, bufProgressData);
       
   233     User::LeaveIfError(RProperty::Set(KUidSystemCategory, (startEndKey+1), bufProgressData));
       
   234     CleanupStack::PopAndDestroy(&bufProgressData);
       
   235     }
       
   236 
       
   237 EXPORT_C void CPublishSifOperationInfo::PublishCompletionL(CSifOperationEndData& aSifOperationEndData)
       
   238     {
       
   239     TUint endKey = 0;
       
   240     HBufC *compGlobalId = aSifOperationEndData.GlobalComponentId().AllocLC();
       
   241 	//Get the key defined for this operation
       
   242     endKey = KeyForGlobalComponentIdL(compGlobalId->Des());
       
   243     CleanupStack::PopAndDestroy(compGlobalId);
       
   244     
       
   245     // Store this key and delete it in case of any leaves
       
   246     SetKeyToDelete(endKey);
       
   247     
       
   248     //Publish end info of operation in defined key
       
   249     RBuf8 bufEndData;
       
   250     bufEndData.CleanupClosePushL();
       
   251     ExternalizeRefObjectL(aSifOperationEndData, bufEndData);
       
   252 
       
   253     User::LeaveIfError(RProperty::Set(KUidSystemCategory, endKey, bufEndData));
       
   254     CleanupStack::PopAndDestroy(&bufEndData);
       
   255     
       
   256     // Wait for KDeleteKeyDelay seconds before deleting this key.
       
   257     if(iDeleteTimer)
       
   258         iDeleteTimer->Cancel();
       
   259     delete iDeleteTimer;
       
   260     iDeleteTimer = CDeleteKeyTimer::NewL(endKey);
       
   261     
       
   262     // Everything finished fine, we need not delete the keys defined for this operation
       
   263     SetKeyToDelete(0);
       
   264     
       
   265     iDeleteTimer->Start();
       
   266 
       
   267     }
       
   268 
       
   269 
       
   270 
       
   271 //////////////////////////
       
   272 // CSifOperationsNotifier
       
   273 //////////////////////////
       
   274 
       
   275 
       
   276 EXPORT_C CSifOperationsNotifier* CSifOperationsNotifier::NewL(MSifOperationsHandler& aHandler)
       
   277     {
       
   278     CSifOperationsNotifier* self = CSifOperationsNotifier::NewLC(aHandler);
       
   279     CleanupStack::Pop(self);
       
   280     return self;
       
   281     }
       
   282 
       
   283 
       
   284 EXPORT_C CSifOperationsNotifier* CSifOperationsNotifier::NewLC(MSifOperationsHandler& aHandler)
       
   285     {
       
   286     CSifOperationsNotifier* self = new (ELeave) CSifOperationsNotifier(aHandler);
       
   287     CleanupStack::PushL(self);
       
   288     self->ConstructL();
       
   289     return self;
       
   290     }
       
   291 
       
   292 CSifOperationsNotifier::CSifOperationsNotifier(MSifOperationsHandler& aHandler):
       
   293     CActive(EPriorityNormal),
       
   294     iHandler(aHandler),
       
   295     iBufferSize(KBufferSize) 
       
   296     {
       
   297     //Empty
       
   298     }
       
   299 
       
   300 
       
   301 void CSifOperationsNotifier::ConstructL()
       
   302     {
       
   303     CActiveScheduler::Add(this);
       
   304     iProperty.Attach(KUidSystemCategory,KSifOperationKey,EOwnerThread);
       
   305     
       
   306     // On first start, the notifier looks for any active operations and 
       
   307     // notifies the client.
       
   308     iNotifierState = EFirstStart;
       
   309     
       
   310     TRequestStatus* status = &iStatus;
       
   311     User::RequestComplete(status, KErrNone);
       
   312     SetActive();
       
   313     }
       
   314 
       
   315 
       
   316 void CSifOperationsNotifier::RunL()
       
   317     {  
       
   318     User::LeaveIfError(iStatus.Int());
       
   319     
       
   320     // Resubscribe for any changes to the global key.
       
   321     WaitForChangeL();
       
   322     
       
   323     if( iNotifierState == EFirstStart)
       
   324         {
       
   325         // Notify the client of any active operation.
       
   326         ActiveOperationsNotificationL();
       
   327         iNotifierState = EWaitForChange;    
       
   328         return;
       
   329         }
       
   330  
       
   331    // Global key change notification received.      
       
   332     RArray<TUint> newKeyArray;
       
   333     GetKeysL(newKeyArray);
       
   334     CleanupClosePushL(newKeyArray);
       
   335     
       
   336     if(iKeyArray.Count() < newKeyArray.Count())
       
   337         {
       
   338         // New Keys added.
       
   339         RBuf8 externalizedBuffer;
       
   340         externalizedBuffer.CleanupClosePushL();
       
   341         
       
   342         // Retrieve the new keys and send the start operation notification to each.
       
   343         for(TInt i = iKeyArray.Count(); i< newKeyArray.Count(); ++i)
       
   344             {
       
   345             externalizedBuffer.Close();
       
   346             GetDataL(newKeyArray[i], iBufferSize, externalizedBuffer);
       
   347             
       
   348             RDesReadStream stream(externalizedBuffer);
       
   349             CleanupClosePushL(stream);
       
   350             // Read the first 4 bytes
       
   351             TSifOperation opType = static_cast<TSifOperation>(stream.ReadInt32L());         
       
   352             if(opType != ESifOperationStart)
       
   353                 {
       
   354                 CleanupStack::PopAndDestroy(&stream);
       
   355                 continue;
       
   356                 }
       
   357             
       
   358             // Release the stream and reopen it.
       
   359             stream.Release();
       
   360             stream.Open(externalizedBuffer);
       
   361            
       
   362             CSifOperationStartData* startData = CSifOperationStartData::NewL(stream);
       
   363             CleanupStack::PushL(startData);
       
   364             
       
   365             //Update iKeyArray with the new key.
       
   366             iKeyArray.AppendL(newKeyArray[i]);
       
   367             
       
   368             iHandler.StartOperationHandler(newKeyArray[i], *startData);
       
   369             CleanupStack::PopAndDestroy(2, &stream);            
       
   370             
       
   371             }
       
   372         CleanupStack::PopAndDestroy(&externalizedBuffer);
       
   373         }
       
   374     else if (iKeyArray.Count() > newKeyArray.Count())
       
   375         {
       
   376         // Keys removed.
       
   377         for(TInt i = 0; i<iKeyArray.Count(); ++i)
       
   378             {
       
   379             // Key present in iKeyArray (the previous array of keys) is no longer
       
   380             // present in the newKeyArray.
       
   381             if(newKeyArray.Find(iKeyArray[i]) == KErrNotFound)
       
   382                 {
       
   383                 CancelSubscribeL(iKeyArray[i]);
       
   384                 iKeyArray.Remove(i);
       
   385                 }
       
   386             }
       
   387         }   
       
   388     CleanupStack::PopAndDestroy(&newKeyArray);
       
   389     }
       
   390 
       
   391 void CSifOperationsNotifier::ActiveOperationsNotificationL()
       
   392     {
       
   393     // Notify the caller of any operation currently in progress.
       
   394     GetKeysL(iKeyArray);
       
   395     
       
   396     RBuf8 externalizedBuffer;
       
   397     
       
   398     for(TInt i=0; i<iKeyArray.Count(); ++i)
       
   399         {
       
   400         externalizedBuffer.Close();
       
   401         GetDataL(iKeyArray[i], iBufferSize, externalizedBuffer);
       
   402         CleanupClosePushL(externalizedBuffer);
       
   403         
       
   404         RDesReadStream stream(externalizedBuffer);
       
   405         CleanupClosePushL(stream);
       
   406         
       
   407         //Read the first 4 bytes
       
   408         TSifOperation opType = static_cast<TSifOperation>(stream.ReadUint32L());
       
   409         if(opType != ESifOperationStart)
       
   410             {
       
   411             // Ignore this key and continue.
       
   412             CleanupStack::PopAndDestroy(2, &externalizedBuffer);
       
   413             continue;
       
   414             }
       
   415         // Release the stream and reopen it.
       
   416         stream.Release();
       
   417         stream.Open(externalizedBuffer);
       
   418         
       
   419         CSifOperationStartData* startData = CSifOperationStartData::NewL(stream);
       
   420         CleanupStack::PushL(startData);
       
   421         iHandler.StartOperationHandler(iKeyArray[i], *startData); 
       
   422         CleanupStack::PopAndDestroy(startData);  
       
   423            
       
   424         CleanupStack::PopAndDestroy(2, &externalizedBuffer);  
       
   425         }
       
   426     
       
   427     }
       
   428 void CSifOperationsNotifier::WaitForChangeL()
       
   429     {   
       
   430     iProperty.Subscribe(iStatus);
       
   431     SetActive();
       
   432     }
       
   433 
       
   434 
       
   435 void CSifOperationsNotifier::GetKeysL(RArray<TUint>& aKeys)
       
   436     {
       
   437     TBuf8<KMaxNumberOfOperations * sizeof(TInt)> keysBuffer;
       
   438     User::LeaveIfError(iProperty.Get(keysBuffer));
       
   439     
       
   440     RDesReadStream stream(keysBuffer);
       
   441     CleanupClosePushL(stream);
       
   442     
       
   443     // Construct the CSifOperationKey object from the buffer.
       
   444     CSifOperationKey* opKey = CSifOperationKey::NewL(stream);
       
   445     CleanupStack::PushL(opKey);
       
   446     
       
   447     for(TInt i=0; i<opKey->StartEndKeys().Count(); ++i)
       
   448         {
       
   449         aKeys.AppendL(opKey->StartEndKeys()[i]);
       
   450         }
       
   451     
       
   452     CleanupStack::PopAndDestroy(2, &stream);
       
   453     }
       
   454 
       
   455 
       
   456 EXPORT_C void CSifOperationsNotifier::SubscribeL(TUint aKey, TBool aSubscribeForProgressNotifications)
       
   457     {
       
   458     User::LeaveIfError(iKeyArray.Find(aKey));
       
   459     
       
   460     // Start End notifier.
       
   461     CSifNotifierBase* startEndNotifier = CSifNotifierBase::NewLC(iHandler, aKey, CSifNotifierBase::EStartEndNotifier);
       
   462     iNotifierArray.AppendL(startEndNotifier);
       
   463     CleanupStack::Pop(startEndNotifier);
       
   464     
       
   465     if(aSubscribeForProgressNotifications)
       
   466         {
       
   467         // Progress Notifier.
       
   468         CSifNotifierBase* progressNotifier = CSifNotifierBase::NewLC(iHandler, aKey+1, CSifNotifierBase::EProgressNotifier);
       
   469         iNotifierArray.AppendL(progressNotifier);
       
   470         CleanupStack::Pop(progressNotifier);
       
   471         }
       
   472     }
       
   473 
       
   474 
       
   475 EXPORT_C void CSifOperationsNotifier::CancelSubscribeL(TUint aKey)
       
   476     {
       
   477     TInt index = iKeyArray.Find(aKey);
       
   478     
       
   479     if(index == KErrNotFound)
       
   480         {
       
   481         // No need to leave.
       
   482         return;
       
   483         }
       
   484     
       
   485     for(TInt i=0; i< iNotifierArray.Count(); ++i)
       
   486         {
       
   487 
       
   488         if(iNotifierArray[i]->Key() == aKey)
       
   489             {
       
   490             delete iNotifierArray[i];
       
   491             iNotifierArray.Remove(i);
       
   492             
       
   493             // Delete progress notification object also, if present.
       
   494             // i now points to the next element
       
   495             if( i <= iNotifierArray.Count()-1 && iNotifierArray[i]->Key() == aKey+1)
       
   496                 {
       
   497                 delete iNotifierArray[i];
       
   498                 iNotifierArray.Remove(i);
       
   499                 }
       
   500             }
       
   501         
       
   502         }
       
   503 
       
   504     }
       
   505 
       
   506 
       
   507 EXPORT_C void CSifOperationsNotifier::CancelSubscribeL()
       
   508     {
       
   509     //Destroy all the notifiers.
       
   510     Cancel();
       
   511     }
       
   512 
       
   513 
       
   514 void CSifOperationsNotifier::DoCancel()
       
   515     {
       
   516     iProperty.Cancel();
       
   517     iNotifierArray.ResetAndDestroy();
       
   518     }
       
   519 
       
   520 TInt CSifOperationsNotifier::RunError(TInt aError)
       
   521     {
       
   522     DEBUG_PRINTF2(_L8("CSifOperationsNotifier::RunError : Error code %d"), aError);
       
   523     // If RunL() leaves due to ActiveOperationsNotificationL(), change the state.
       
   524     if(iNotifierState == EFirstStart)
       
   525         {
       
   526         iNotifierState = EWaitForChange;
       
   527         }
       
   528     (void)aError;
       
   529     return KErrNone;
       
   530     }
       
   531 
       
   532 
       
   533 CSifOperationsNotifier::~CSifOperationsNotifier()
       
   534     {
       
   535     Cancel();
       
   536     iProperty.Close();
       
   537     iKeyArray.Close();
       
   538     }
       
   539 
       
   540 
       
   541 
       
   542 //////////////////////////
       
   543 // CSifNotifierBase
       
   544 //////////////////////////
       
   545 
       
   546 
       
   547 EXPORT_C CSifNotifierBase* CSifNotifierBase::NewL(MSifOperationsHandler& aHandler, TUint aKey, TNotifierType aType)
       
   548     {
       
   549     CSifNotifierBase* self = CSifNotifierBase::NewLC(aHandler, aKey, aType);
       
   550     CleanupStack::Pop(self);
       
   551     return self;
       
   552     }
       
   553 
       
   554 
       
   555 EXPORT_C CSifNotifierBase* CSifNotifierBase::NewLC(MSifOperationsHandler& aHandler, TUint aKey, TNotifierType aType)
       
   556     {
       
   557     CSifNotifierBase* self = new (ELeave) CSifNotifierBase(aHandler, aKey, aType);
       
   558     CleanupStack::PushL(self);
       
   559     self->ConstructL();
       
   560     return self;
       
   561     }
       
   562 
       
   563 CSifNotifierBase::CSifNotifierBase(MSifOperationsHandler& aHandler, TUint aKey, TNotifierType aType):
       
   564     CActive(EPriorityNormal),
       
   565     iHandler(aHandler),
       
   566     iKey(aKey),
       
   567     iBufferSize(KBufferSize),
       
   568     iType(aType)
       
   569     {
       
   570     //Empty
       
   571     }
       
   572 
       
   573 
       
   574 void CSifNotifierBase::ConstructL()
       
   575     {
       
   576     CActiveScheduler::Add(this);
       
   577     iProperty.Attach(KUidSystemCategory,iKey,EOwnerThread);
       
   578     // Subscribe to the key and wait for a notification.
       
   579     WaitForChangeL();
       
   580     }
       
   581 
       
   582 
       
   583 void CSifNotifierBase::RunL()
       
   584     {
       
   585     User::LeaveIfError(iStatus.Int());
       
   586     
       
   587     //Resubscribe for any changes.
       
   588     WaitForChangeL();
       
   589     
       
   590     RBuf8 externalizedBuffer;
       
   591     GetDataL(iKey, iBufferSize, externalizedBuffer);  
       
   592     externalizedBuffer.CleanupClosePushL();
       
   593     
       
   594     RDesReadStream stream(externalizedBuffer);
       
   595     CleanupClosePushL(stream);
       
   596     
       
   597     switch (iType)
       
   598         {
       
   599         case EStartEndNotifier:
       
   600             {
       
   601             //Read the first 4 bytes
       
   602             TSifOperation opType = static_cast<TSifOperation>(stream.ReadInt32L());
       
   603             stream.Release();
       
   604             stream.Open(externalizedBuffer);
       
   605             switch(opType)
       
   606                 {
       
   607                 case ESifOperationEnd:
       
   608                     {
       
   609                     CSifOperationEndData* endData = CSifOperationEndData::NewL(stream);
       
   610                     CleanupStack::PushL(endData);
       
   611                     iHandler.EndOperationHandler(*endData);
       
   612                     CleanupStack::PopAndDestroy(endData);
       
   613                     break;
       
   614                     }
       
   615                     
       
   616                 default:
       
   617                     // Cannot receive a start notification here !
       
   618                     User::Leave(KErrNotSupported);
       
   619                     break; 
       
   620                 }            
       
   621             }
       
   622             
       
   623          break;
       
   624             
       
   625         case EProgressNotifier:
       
   626             {
       
   627             CSifOperationProgressData* progressData = CSifOperationProgressData::NewL(stream);
       
   628             CleanupStack::PushL(progressData);
       
   629             iHandler.ProgressOperationHandler(*progressData);
       
   630             CleanupStack::PopAndDestroy(progressData);
       
   631             }
       
   632         }
       
   633 
       
   634     
       
   635     CleanupStack::PopAndDestroy(2, &externalizedBuffer);
       
   636     }
       
   637 
       
   638 
       
   639 
       
   640 void CSifNotifierBase::WaitForChangeL()
       
   641     {
       
   642     iProperty.Subscribe(iStatus);
       
   643     SetActive();
       
   644     }
       
   645 
       
   646 
       
   647 TInt CSifNotifierBase::RunError(TInt aError)
       
   648     {
       
   649     DEBUG_PRINTF2(_L8("CSifNotifierBase::RunError : Error code %d"), aError);
       
   650     (void)aError;
       
   651     return KErrNone;
       
   652     }
       
   653 
       
   654 TUint CSifNotifierBase::Key()
       
   655     {
       
   656     return iKey;
       
   657     }
       
   658 
       
   659 void CSifNotifierBase::DoCancel()
       
   660     {
       
   661     iProperty.Cancel();
       
   662     }
       
   663 
       
   664 
       
   665 CSifNotifierBase::~CSifNotifierBase()
       
   666     {
       
   667     Cancel();
       
   668     }
       
   669 
       
   670 
       
   671 
       
   672 /////////////////////
       
   673 // CSifOperationKey
       
   674 /////////////////////
       
   675 
       
   676 CSifOperationKey::CSifOperationKey()
       
   677     {
       
   678     // empty
       
   679     }
       
   680 
       
   681 CSifOperationKey::~CSifOperationKey()
       
   682     {
       
   683     iStartEndKeyArray.Close();
       
   684     }
       
   685 
       
   686 EXPORT_C CSifOperationKey* CSifOperationKey::NewL()
       
   687     {
       
   688     CSifOperationKey *self = CSifOperationKey::NewLC();
       
   689     CleanupStack::Pop(self);
       
   690     return self;
       
   691     }
       
   692 
       
   693 CSifOperationKey* CSifOperationKey::NewLC()
       
   694     {
       
   695     CSifOperationKey *self = new(ELeave) CSifOperationKey();
       
   696     CleanupStack::PushL(self);
       
   697     return self;
       
   698     }
       
   699 
       
   700 CSifOperationKey* CSifOperationKey::NewL(RReadStream& aStream)
       
   701     {
       
   702     CSifOperationKey *self = new(ELeave) CSifOperationKey();
       
   703     CleanupStack::PushL(self);
       
   704     self->InternalizeL(aStream);
       
   705     CleanupStack::Pop(self);
       
   706     return self;
       
   707     }
       
   708 
       
   709 EXPORT_C void CSifOperationKey::ExternalizeL(RWriteStream& aStream) const
       
   710     {
       
   711     TInt count = iStartEndKeyArray.Count();
       
   712     aStream.WriteUint32L(count);
       
   713     for(TInt i=0 ; i< count; ++i)
       
   714         {
       
   715         aStream.WriteUint32L(iStartEndKeyArray[i]);
       
   716         }
       
   717     }
       
   718     
       
   719 void CSifOperationKey::InternalizeL(RReadStream& aStream)
       
   720     {
       
   721     TInt count = aStream.ReadUint32L();
       
   722     for(TInt i=0 ; i< count; ++i)
       
   723         {
       
   724         iStartEndKeyArray.AppendL(aStream.ReadUint32L());
       
   725         }
       
   726     }
       
   727 
       
   728 const RArray<TUint>& CSifOperationKey::StartEndKeys() const
       
   729     {
       
   730     return iStartEndKeyArray;
       
   731     }
       
   732 
       
   733 void CSifOperationKey::AddKeyL(TUint aKey)
       
   734     {
       
   735     iStartEndKeyArray.AppendL(aKey);
       
   736     }
       
   737 
       
   738 void CSifOperationKey::DeleteKey(TUint aPos)
       
   739     {
       
   740     iStartEndKeyArray.Remove(aPos);
       
   741     }
       
   742 
       
   743 
       
   744 /////////////////////
       
   745 // CDeleteKeyTimer
       
   746 /////////////////////
       
   747 
       
   748 
       
   749 CDeleteKeyTimer::CDeleteKeyTimer() : CTimer(EPriorityLow)
       
   750     {
       
   751     CActiveScheduler::Add(this);
       
   752     }
       
   753 
       
   754 CDeleteKeyTimer::~CDeleteKeyTimer()
       
   755     {
       
   756     Cancel();
       
   757     }
       
   758 
       
   759 CDeleteKeyTimer* CDeleteKeyTimer::NewL(const TUint aKey)
       
   760     {
       
   761     CDeleteKeyTimer* self = new(ELeave) CDeleteKeyTimer();
       
   762     CleanupStack::PushL(self);
       
   763     self->ConstructL(aKey);
       
   764     CleanupStack::Pop(self);
       
   765     return self;
       
   766     }
       
   767 
       
   768 void CDeleteKeyTimer::ConstructL(const TUint aKey)
       
   769     {
       
   770     CTimer::ConstructL();
       
   771     iKey = aKey;
       
   772     }
       
   773 
       
   774 void CDeleteKeyTimer::Start()
       
   775     {
       
   776     After(KDeleteKeyDelay);
       
   777     }
       
   778 
       
   779 void CDeleteKeyTimer::RunL()
       
   780     {
       
   781     // Publish(remove this key from existing info) the remaining keys in the global SIF key.
       
   782     TBuf8<KMaxNumberOfOperations * sizeof(TInt)> buf;
       
   783 	RProperty oprnProperty;
       
   784 	CleanupClosePushL(oprnProperty);
       
   785 	
       
   786 	oprnProperty.Attach(KUidSystemCategory, KSifOperationKey);
       
   787     TInt err = oprnProperty.Get(buf);
       
   788     User::LeaveIfError(err);
       
   789     
       
   790     RDesReadStream readStream(buf);
       
   791     CleanupClosePushL(readStream);
       
   792     CSifOperationKey* opKey = CSifOperationKey::NewL(readStream);
       
   793     CleanupStack::PushL(opKey);
       
   794 
       
   795     //Find the position of the key 
       
   796     TInt pos = opKey->StartEndKeys().Find(iKey);
       
   797     
       
   798     // Delete key, externalize the updated CSifOperationKey object and publish it.
       
   799     opKey->DeleteKey(pos);
       
   800     
       
   801     RBuf8 operationKeyData;
       
   802     operationKeyData.CleanupClosePushL();
       
   803     ExternalizeRefObjectL(*opKey, operationKeyData);
       
   804     
       
   805     User::LeaveIfError(oprnProperty.Set(operationKeyData));
       
   806     
       
   807     // StartEnd Key.
       
   808     RProperty::Delete(KUidSystemCategory, iKey);
       
   809     // Progress Key.
       
   810     RProperty::Delete(KUidSystemCategory, (iKey+1));
       
   811     
       
   812     CleanupStack::PopAndDestroy(4, &oprnProperty);
       
   813     }
       
   814 
       
   815 
       
   816 TInt CDeleteKeyTimer::RunError(TInt aError)
       
   817     {
       
   818     DEBUG_PRINTF2(_L8("CDeleteKeyTimer::RunError : Error code %d"), aError);
       
   819     (void)aError;
       
   820     
       
   821     // StartEnd Key.
       
   822     RProperty::Delete(KUidSystemCategory, iKey);
       
   823     // Progress Key.
       
   824     RProperty::Delete(KUidSystemCategory, (iKey+1));
       
   825     return KErrNone;
       
   826     }