presetserver/serversrc/Psserver.cpp
changeset 0 09774dfdd46b
child 12 608f67c22514
equal deleted inserted replaced
-1:000000000000 0:09774dfdd46b
       
     1 /*
       
     2 * Copyright (c) 2006-2006 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 "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:  Preset server implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <pscommon.h>
       
    20 #include <sbdefs.h>
       
    21 
       
    22 #include "psdatabasecleanup.h"
       
    23 #include "psdebug.h"
       
    24 #include "pspendingpreset.h"
       
    25 #include "psscheduler.h"
       
    26 #include "psserver.h"
       
    27 #include "pssession.h"
       
    28 #include "psshutdown.h"
       
    29 #include "psutils.h"
       
    30 
       
    31 using namespace conn;
       
    32 
       
    33 const TInt KPSPriority = CActive::EPriorityStandard;    // Priority of the preset server.
       
    34 
       
    35 const TInt KPSShutdownTime = 500000; // The time in microseconds between the last client disconnecting and the server being closed.
       
    36 const TInt KPSCachedNotificationCleanerPeriod = 60000000; // The period in microseconds between checking for unused cached notifications.
       
    37 const TInt KPSCachedNotificationKeepAliveTime = 300000000; // The amount of time in microseconds to keep cached notifications alive after they have been added.
       
    38 
       
    39 // ======== LOCAL FUNCTIONS ========
       
    40 
       
    41 namespace
       
    42     {
       
    43 
       
    44 #ifdef _DEBUG
       
    45 
       
    46     // ---------------------------------------------------------------------------
       
    47     // Panics the process.
       
    48     // ---------------------------------------------------------------------------
       
    49     //
       
    50     void Panic( TInt aReason )
       
    51         {
       
    52         User::Panic( KPSServerName, aReason );
       
    53         }
       
    54 
       
    55 #endif // _DEBUG
       
    56 
       
    57     // ---------------------------------------------------------------------------
       
    58     // Sorts the array by priority of the notification observers. Descending order!
       
    59     // ---------------------------------------------------------------------------
       
    60     //
       
    61     TInt SortPresetObserverArrayByPriority( const RMessage2& aMessage1, const RMessage2& aMessage2 )
       
    62         {
       
    63         if ( aMessage1.Int1() < aMessage2.Int1() )
       
    64             {
       
    65             return 1;
       
    66             }
       
    67         else if ( aMessage1.Int1() > aMessage2.Int1() )
       
    68             {
       
    69             return -1;
       
    70             }
       
    71         else
       
    72             {
       
    73             return 0;
       
    74             }
       
    75         }
       
    76 
       
    77     // ---------------------------------------------------------------------------
       
    78     // Initializes the server process.
       
    79     // ---------------------------------------------------------------------------
       
    80     //
       
    81     void InitServerL()
       
    82         {
       
    83         User::RenameThread( KPSServerName );
       
    84         
       
    85         TFindServer findServer( KPSServerName );
       
    86         TFullName fullName;
       
    87         
       
    88         if ( findServer.Next( fullName ) ) // Server has not yet been started.
       
    89             {
       
    90             CPSScheduler* scheduler = new ( ELeave ) CPSScheduler;
       
    91             CleanupStack::PushL( scheduler );
       
    92             CActiveScheduler::Install( scheduler );
       
    93 
       
    94             CPSServer* server = CPSServer::NewL();
       
    95             CleanupStack::Pop( scheduler );
       
    96             scheduler->SetServer( server );
       
    97 
       
    98             // Attention! Absolutely no code that can leave may be run after doing the rendezvous!
       
    99 
       
   100             RProcess().Rendezvous( KErrNone );        
       
   101 
       
   102             CActiveScheduler::Start();
       
   103             
       
   104             delete server;
       
   105             delete scheduler;
       
   106             }
       
   107         else
       
   108             {
       
   109             RProcess().Rendezvous( KErrNone );
       
   110             }
       
   111         }
       
   112 
       
   113     }
       
   114     
       
   115 // ======== MEMBER FUNCTIONS ========
       
   116 
       
   117 // ---------------------------------------------------------------------------
       
   118 // Constructor.
       
   119 // ---------------------------------------------------------------------------
       
   120 //
       
   121 CPSServer::CPSServer()
       
   122     : CServer2( KPSPriority ), iDatabase( *this ), iShutdownDelay( KPSShutdownTime )
       
   123     {
       
   124     }
       
   125 
       
   126 // ---------------------------------------------------------------------------
       
   127 // Second-phase constructor.
       
   128 // ---------------------------------------------------------------------------
       
   129 //
       
   130 void CPSServer::ConstructL()
       
   131     {
       
   132     PSDEBUG( "CPSServer::ConstructL() [enter]" );
       
   133 
       
   134     User::LeaveIfError( iFs.Connect() );
       
   135 
       
   136     TFileName databaseFullName;
       
   137     PSUtils::GetDatabaseFullNameL( databaseFullName );
       
   138 
       
   139     iDatabase.OpenL( iFs, databaseFullName );
       
   140 
       
   141     iShutdown = CPSShutdown::NewL();
       
   142     iCleanup = CPSDatabaseCleanup::NewL( iDatabase );
       
   143 
       
   144     iCachedNotificationCleaner = CPeriodic::NewL( CActive::EPriorityStandard );
       
   145     iCachedNotificationCleaner->Start( KPSCachedNotificationCleanerPeriod, KPSCachedNotificationCleanerPeriod,
       
   146                                        TCallBack( StaticCleanCachedNotifications, this ) ); 
       
   147     
       
   148     iPropertyObserver = CPSPropertyObserver::NewL( *this, KUidSystemCategory, 
       
   149                                                    KUidBackupRestoreKey, RProperty::EInt);
       
   150     
       
   151     StartL( KPSServerName );
       
   152 
       
   153     PSDEBUG( "CPSServer::ConstructL() [exit]" );
       
   154     }
       
   155 
       
   156 // ---------------------------------------------------------------------------
       
   157 // Two-phased constructor.
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 CPSServer* CPSServer::NewL()
       
   161     {
       
   162     CPSServer* self = new ( ELeave ) CPSServer;
       
   163     CleanupStack::PushL( self );
       
   164     self->ConstructL();
       
   165     CleanupStack::Pop( self );
       
   166     return self;
       
   167     }
       
   168 
       
   169 // ---------------------------------------------------------------------------
       
   170 // Destructor.
       
   171 // ---------------------------------------------------------------------------
       
   172 //
       
   173 CPSServer::~CPSServer()
       
   174     {
       
   175     PSDEBUG( "CPSServer::~CPSServer() [enter]" );
       
   176 
       
   177     Cancel();
       
   178     
       
   179     delete iPropertyObserver;
       
   180     delete iCachedNotificationCleaner;
       
   181     delete iShutdown;
       
   182     delete iCleanup;
       
   183 
       
   184     iDatabase.Close();
       
   185     iFs.Close();
       
   186 
       
   187     while ( iPresetObservers.Count() )
       
   188         {
       
   189         if ( !iPresetObservers[0].IsNull() )
       
   190             {
       
   191             iPresetObservers[0].Complete( KErrServerTerminated );
       
   192             }
       
   193         iPresetObservers.Remove( 0 );
       
   194         }
       
   195     iPresetObservers.Close();
       
   196 
       
   197     iNotifications.Close();
       
   198     iPendingPresets.ResetAndDestroy();
       
   199 
       
   200     PSDEBUG( "CPSServer::~CPSServer() [exit]" );
       
   201     }
       
   202 
       
   203 // ---------------------------------------------------------------------------
       
   204 // Returns the current message.
       
   205 // ---------------------------------------------------------------------------
       
   206 //
       
   207 const RMessage2& CPSServer::Message() const
       
   208     {
       
   209     return CServer2::Message();
       
   210     }
       
   211 
       
   212 // ---------------------------------------------------------------------------
       
   213 // Returns the database.
       
   214 // ---------------------------------------------------------------------------
       
   215 //
       
   216 RPSDatabase& CPSServer::Database()
       
   217     {
       
   218     return iDatabase;
       
   219     }
       
   220 
       
   221 // ---------------------------------------------------------------------------
       
   222 // Panics the client.
       
   223 // ---------------------------------------------------------------------------
       
   224 //
       
   225 void CPSServer::PanicClient( TInt aReason ) const
       
   226     {
       
   227     Message().Panic( KPSServerName, aReason );
       
   228     }
       
   229 
       
   230 // ---------------------------------------------------------------------------
       
   231 // Increments the session count.
       
   232 // ---------------------------------------------------------------------------
       
   233 //
       
   234 void CPSServer::IncrementSessionCount()
       
   235     {
       
   236     iSessionCount++;
       
   237     
       
   238     iShutdown->Cancel();
       
   239     }
       
   240 
       
   241 // ---------------------------------------------------------------------------
       
   242 // Decrements the session count.
       
   243 // ---------------------------------------------------------------------------
       
   244 //
       
   245 void CPSServer::DecrementSessionCount()
       
   246     {
       
   247     iSessionCount--;
       
   248     
       
   249     if ( iSessionCount == 0 ) // Last session was closed, so we need to start the shutdown timer.
       
   250         {
       
   251         iShutdown->Start( iShutdownDelay );
       
   252         }
       
   253 
       
   254     __ASSERT_DEBUG( iSessionCount >= 0, Panic( KErrCorrupt ) );
       
   255     }
       
   256 
       
   257 // ---------------------------------------------------------------------------
       
   258 // Called when a session is disconnected.
       
   259 // ---------------------------------------------------------------------------
       
   260 //
       
   261 void CPSServer::SessionDisconnected( const RMessage2& aMessage )
       
   262     {
       
   263     PSDEBUG( "CPSServer::SessionDisconnected( RMessage2& ) [enter]" );
       
   264 
       
   265     for ( TInt i = 0; i < iPresetObservers.Count(); i++ )
       
   266         {
       
   267         const RMessage2& message = iPresetObservers[i];
       
   268         
       
   269         if ( message.Session() == aMessage.Session() )
       
   270             {
       
   271             if ( !message.IsNull() )
       
   272                 {
       
   273                 message.Complete( KErrDied );
       
   274                 }
       
   275             iPresetObservers.Remove( i );
       
   276             i--;
       
   277             }
       
   278         }
       
   279 
       
   280     PSDEBUG( "CPSServer::SessionDisconnected( RMessage2& ) [exit]" );
       
   281     }
       
   282 
       
   283 // ---------------------------------------------------------------------------
       
   284 // Appends a preset observer.
       
   285 // ---------------------------------------------------------------------------
       
   286 //
       
   287 void CPSServer::AppendPresetObserverL( const RMessage2& aMessage )
       
   288     {
       
   289     PSDEBUG( "CPSServer::AppendPresetObserverL( RMessage2& ) [enter]" );
       
   290 
       
   291     TInt idx = PresetObserverIndex( aMessage );
       
   292     
       
   293     if ( idx != KErrNotFound )
       
   294         {
       
   295         PSDEBUG( "CPSServer::AppendPresetObserverL - Preset observer already found" );
       
   296         User::Leave( KErrAlreadyExists );
       
   297         }
       
   298 
       
   299     TPckgBuf<TPSNotifyDataPackage> data;
       
   300     aMessage.ReadL( 2, data );
       
   301     
       
   302     TInt nextUnhandledNotificationIndex = NextUnhandledNotificationIndexById( data().iNotificationId, aMessage.Int1() );
       
   303     
       
   304     if ( data().iNotificationId > 0 && nextUnhandledNotificationIndex >= 0 )
       
   305         {
       
   306         PSDEBUG2( "CPSServer::AppendPresetObserverL - Cached notification that was missed was found at index %d", nextUnhandledNotificationIndex );
       
   307 
       
   308         aMessage.WriteL( 2, TPckgC<TPSNotifyDataPackage>( iNotifications[nextUnhandledNotificationIndex] ) );
       
   309         aMessage.Complete( KErrNone ); 
       
   310         }
       
   311     else
       
   312         {
       
   313         PSDEBUG( "CPSServer::AppendPresetObserverL - No cached notifications of interest were found, starting to observe further ones" );
       
   314         iPresetObservers.AppendL( RMessage2( aMessage ) );
       
   315         }
       
   316 
       
   317     PSDEBUG( "CPSServer::AppendPresetObserverL( RMessage2& ) [enter]" );
       
   318     }
       
   319 
       
   320 // ---------------------------------------------------------------------------
       
   321 // Removes a preset observer and completes it with KErrCancel.
       
   322 // ---------------------------------------------------------------------------
       
   323 //
       
   324 void CPSServer::RemovePresetObserver( const RMessage2& aMessage )
       
   325     {
       
   326     TInt idx = PresetObserverIndex( aMessage );
       
   327 
       
   328     if ( idx >= 0 )
       
   329         {
       
   330         if ( !iPresetObservers[idx].IsNull() )
       
   331             {
       
   332             iPresetObservers[idx].Complete( KErrCancel );
       
   333             }
       
   334         iPresetObservers.Remove( idx );
       
   335         }
       
   336     }
       
   337 
       
   338 // ---------------------------------------------------------------------------
       
   339 // Returns the index of a given preset observer.
       
   340 // ---------------------------------------------------------------------------
       
   341 //
       
   342 TInt CPSServer::PresetObserverIndex( const RMessage2& aMessage ) const
       
   343     {
       
   344     TInt idx = KErrNotFound;
       
   345         
       
   346     CSession2* currentSession = aMessage.Session();
       
   347         
       
   348     for ( TInt i = 0; i < iPresetObservers.Count(); i++ )
       
   349         {
       
   350         const RMessage2& message = iPresetObservers[i];
       
   351 
       
   352         if ( !message.IsNull() && message.Session() == currentSession && message.Int0() == aMessage.Int0() )
       
   353             {
       
   354             idx = i;
       
   355             /*lint -save -e960 (Note -- Violates MISRA Required Rule 58, non-switch break used)*/
       
   356             break;
       
   357             /*lint -restore*/
       
   358             }
       
   359         }
       
   360     
       
   361     return idx;
       
   362     }
       
   363 
       
   364 // ---------------------------------------------------------------------------
       
   365 // Appends a pending preset.
       
   366 // ---------------------------------------------------------------------------
       
   367 //
       
   368 void CPSServer::AppendPendingPresetL( TInt aId )
       
   369     {
       
   370     TInt idx = PendingPresetIndex( aId );
       
   371 
       
   372     if ( idx == KErrNotFound )
       
   373         {
       
   374         CPSPendingPreset* preset = CPSPendingPreset::NewL( aId );
       
   375         CleanupStack::PushL( preset );
       
   376         iPendingPresets.AppendL( preset );
       
   377         CleanupStack::Pop( preset );
       
   378         }
       
   379     else
       
   380         {
       
   381         User::Leave( KErrLocked );
       
   382         }
       
   383     }
       
   384 
       
   385 // ---------------------------------------------------------------------------
       
   386 // Commits a pending preset.
       
   387 // ---------------------------------------------------------------------------
       
   388 //
       
   389 void CPSServer::CommitPendingPresetL( TInt aId )
       
   390     {
       
   391     TInt idx = PendingPresetIndex( aId );
       
   392 
       
   393     if ( idx >= 0 )
       
   394         {
       
   395         CPSPendingPreset* preset = iPendingPresets[idx];
       
   396         iDatabase.CommitPresetL( *preset );
       
   397         iPendingPresets.Remove( idx );
       
   398         delete preset;
       
   399         }
       
   400     else
       
   401         {
       
   402         User::Leave( KErrNotReady );
       
   403         }
       
   404     }
       
   405 
       
   406 // ---------------------------------------------------------------------------
       
   407 // Removes a pending preset from the array.
       
   408 // ---------------------------------------------------------------------------
       
   409 //
       
   410 void CPSServer::RemovePendingPreset( TInt aId )
       
   411     {
       
   412     TInt idx = PendingPresetIndex( aId );
       
   413     
       
   414     if ( idx >= 0 )
       
   415         {
       
   416         CPSPendingPreset* preset = iPendingPresets[idx];
       
   417         iPendingPresets.Remove( idx );
       
   418         delete preset;
       
   419         }
       
   420     }
       
   421 
       
   422 // ---------------------------------------------------------------------------
       
   423 // Sets the index of a pending preset.
       
   424 // ---------------------------------------------------------------------------
       
   425 //
       
   426 void CPSServer::SetPendingPresetIndexL( TInt aId, TInt aIndex )
       
   427     {
       
   428     TInt idx = PendingPresetIndex( aId );
       
   429     
       
   430     if ( idx >= 0 )
       
   431         {
       
   432         iPendingPresets[idx]->SetIndex( aIndex ); 
       
   433         }
       
   434     else
       
   435         {
       
   436         User::Leave( KErrNotReady );
       
   437         }
       
   438     }
       
   439 
       
   440 // ---------------------------------------------------------------------------
       
   441 // Sets the name of a pending preset.
       
   442 // ---------------------------------------------------------------------------
       
   443 //
       
   444 void CPSServer::SetPendingPresetNameL( TInt aId, const TDesC& aName )
       
   445     {
       
   446     TInt idx = PendingPresetIndex( aId );
       
   447     
       
   448     if ( idx >= 0 )
       
   449         {
       
   450         iPendingPresets[idx]->SetNameL( aName ); 
       
   451         }
       
   452     else
       
   453         {
       
   454         User::Leave( KErrNotReady );
       
   455         }
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // Sets the data of a pending preset.
       
   460 // ---------------------------------------------------------------------------
       
   461 //
       
   462 void CPSServer::SetPendingPresetDataL( TInt aId, const TDesC8& aData )
       
   463     {
       
   464     TInt idx = PendingPresetIndex( aId );
       
   465     
       
   466     if ( idx >= 0 )
       
   467         {
       
   468         iPendingPresets[idx]->SetDataL( aData ); 
       
   469         }
       
   470     else
       
   471         {
       
   472         User::Leave( KErrNotReady );
       
   473         }
       
   474     }
       
   475 
       
   476 // ---------------------------------------------------------------------------
       
   477 // From class CSession2
       
   478 // Creates a new session.
       
   479 // ---------------------------------------------------------------------------
       
   480 //
       
   481 CSession2* CPSServer::NewSessionL( const TVersion& aVersion, const RMessage2& /*aMessage*/ ) const
       
   482     {
       
   483     TVersion currentVersion( KPSVersionMajor, KPSVersionMinor, KPSVersionBuild );
       
   484     
       
   485     if ( !User::QueryVersionSupported( currentVersion, aVersion ) )
       
   486         {
       
   487         User::Leave( KErrNotSupported );
       
   488         }
       
   489 
       
   490     return CPSSession::NewL( *const_cast<CPSServer*>( this ) );
       
   491     }
       
   492 
       
   493 // ---------------------------------------------------------------------------
       
   494 // From class MPSPresetObserver
       
   495 // Invoked when a preset is changed.
       
   496 // ---------------------------------------------------------------------------
       
   497 //
       
   498 void CPSServer::HandlePresetChangedL( TInt aId, TUid aDataHandler, MPSPresetObserver::TPSReason aReason )
       
   499     {
       
   500     NotifyPresetObserversL( aId, aDataHandler, aReason );
       
   501     
       
   502     if (aReason == MPSPresetObserver::EPSDeleted)
       
   503     	{
       
   504     	iCleanup->RequestCleanupCheck();
       
   505     	}
       
   506     }
       
   507 
       
   508 // ---------------------------------------------------------------------------
       
   509 // Returns the index of a pending preset matching the supplied id.
       
   510 // ---------------------------------------------------------------------------
       
   511 //
       
   512 TInt CPSServer::PendingPresetIndex( TInt aId ) const
       
   513     {
       
   514     TInt idx = KErrNotFound;
       
   515 
       
   516     for ( TInt i = 0; i < iPendingPresets.Count(); i++ )
       
   517         {
       
   518         if ( iPendingPresets[i]->Id() == aId )
       
   519             {
       
   520             idx = i;
       
   521             /*lint -save -e960 (Note -- Violates MISRA Required Rule 58, non-switch break used)*/
       
   522             break;
       
   523             /*lint -restore*/
       
   524             }
       
   525         }
       
   526 
       
   527     return idx;
       
   528     }
       
   529 
       
   530 // ---------------------------------------------------------------------------
       
   531 // Notifies the preset observers.
       
   532 // ---------------------------------------------------------------------------
       
   533 //
       
   534 void CPSServer::NotifyPresetObserversL( TInt aId, TUid aDataHandler, MPSPresetObserver::TPSReason aReason )
       
   535     {
       
   536     PSDEBUG5( "CPSServer::NotifyPresetObserversL( aId = %d, aDataHandler = %d, aReason = %d ) - Notifications cached: %d", aId, aDataHandler.iUid, aReason, iNotifications.Count() );
       
   537 
       
   538     TTime current;
       
   539     current.UniversalTime();
       
   540 
       
   541     iCachedNotificationId++; // Running cached notification identifier is incremented here. Must be done before the data package is constructed.
       
   542     
       
   543     TPSNotifyDataPackage data = { aId, aDataHandler, aReason, iCachedNotificationId, current };
       
   544     iNotifications.AppendL( data );
       
   545 
       
   546     // Sorts the preset observers array so, that presets are first, then other observers.
       
   547     // This is done to ensure that presets are notified first, just in case.
       
   548     iPresetObservers.Sort( TLinearOrder<RMessage2>( ::SortPresetObserverArrayByPriority ) );
       
   549 
       
   550     TInt skipped = 0; // Number of observers that will not be notified, i.e. are skipped.
       
   551 
       
   552     while ( iPresetObservers.Count() && skipped < iPresetObservers.Count() )
       
   553         {
       
   554         const RMessage2& message = iPresetObservers[skipped];
       
   555 
       
   556         if ( message.IsNull() )
       
   557             {
       
   558             iPresetObservers.Remove( skipped ); // Dead notifiers are removed from the array.
       
   559             }
       
   560         else
       
   561             {
       
   562             TPckgBuf<TPSNotifyDataPackage> msgData;
       
   563             message.ReadL( 2, msgData );
       
   564 
       
   565             TInt observedPresetId = message.Int1();
       
   566 
       
   567             // If the observer is interested in this preset or it is interested in them all (KErrNotFound),
       
   568             // notify it about the change.
       
   569             if ( aId == observedPresetId || observedPresetId == KErrNotFound )
       
   570                 {
       
   571                 message.WriteL( 2, TPckgC<TPSNotifyDataPackage>( data ) );
       
   572                 message.Complete( KErrNone );
       
   573                 
       
   574                 iPresetObservers.Remove( skipped );
       
   575                 }
       
   576             else
       
   577                 {
       
   578                 skipped++;
       
   579                 }
       
   580             }
       
   581         }
       
   582     }
       
   583 
       
   584 // ---------------------------------------------------------------------------
       
   585 // Cleanup routine for deleting unused cached notifications.
       
   586 // ---------------------------------------------------------------------------
       
   587 //
       
   588 TInt CPSServer::NextUnhandledNotificationIndexById( TUint64 aHandledNotificationId, TInt aObservedPresetId )
       
   589     {
       
   590     TInt index = KErrNotFound;
       
   591     
       
   592     for ( TInt i = 0; i < iNotifications.Count() && index == KErrNotFound; i++ )
       
   593         {
       
   594         if ( iNotifications[i].iNotificationId > aHandledNotificationId )
       
   595             {
       
   596             if ( iNotifications[i].iId == aObservedPresetId || aObservedPresetId == KErrNotFound )
       
   597                 {
       
   598                 index = i;
       
   599                 }
       
   600             }
       
   601         }
       
   602     
       
   603     return index;
       
   604     }
       
   605 
       
   606 // ---------------------------------------------------------------------------
       
   607 // Cleanup routine for deleting unused cached notifications.
       
   608 // ---------------------------------------------------------------------------
       
   609 //
       
   610 TInt CPSServer::StaticCleanCachedNotifications( TAny* aSelf )
       
   611     {
       
   612     CPSServer* self = static_cast<CPSServer*>( aSelf );
       
   613     if ( self )
       
   614         {
       
   615         PSDEBUG2( "CPSServer::StaticCleanCachedNotifications [enter] - iNotifications.Count() = %d", self->iNotifications.Count() );
       
   616 
       
   617         TTime current;
       
   618         current.UniversalTime();
       
   619         
       
   620         for ( TInt i = 0; i < self->iNotifications.Count(); i++ )
       
   621             {
       
   622             TInt64 diff = current.MicroSecondsFrom( self->iNotifications[i].iNotificationTime ).Int64();
       
   623 
       
   624             if ( diff > KPSCachedNotificationKeepAliveTime )
       
   625                 {
       
   626                 PSDEBUG2( "CPSServer::StaticCleanCachedNotifications - Removing cached notification entry from index with time difference of %d seconds", diff / 1000000 ); 
       
   627                 self->iNotifications.Remove( i );
       
   628                 i--;
       
   629                 }
       
   630             }
       
   631         
       
   632         self->iNotifications.Compress();
       
   633 
       
   634         PSDEBUG2( "CPSServer::StaticCleanCachedNotifications [exit] - iNotifications.Count() = %d", self->iNotifications.Count() );
       
   635         }
       
   636 
       
   637     return KErrNone;
       
   638     }
       
   639     
       
   640 // ---------------------------------------------------------------------------
       
   641 // From class MPSPropertyChangeObserver
       
   642 // Invoked when a TInt type property is changed.
       
   643 // ---------------------------------------------------------------------------
       
   644 //
       
   645 void CPSServer::HandlePropertyChangeL( const TUid& /* aCategory */, const TUint /* aKey */, const TInt aValue )
       
   646     {
       
   647     PSDEBUG2( "CPSServer::HandlePropertyChangeL( aValue = %d )", aValue);
       
   648     TUint backupPart = aValue & KBURPartTypeMask; 
       
   649     if ( backupPart != EBURUnset && backupPart != EBURNormal ) // backup or restore -> shutdown when possible.
       
   650         {
       
   651         iShutdownDelay = 0;        
       
   652         if ( iSessionCount == 0 )
       
   653             {
       
   654             iShutdown->Start( iShutdownDelay );
       
   655             }
       
   656         }
       
   657     else
       
   658         {
       
   659         PSDEBUG("CPSServer::HandlePropertyChangeL - no backup/restore ongoing" );
       
   660         }        
       
   661     }
       
   662 
       
   663 // ---------------------------------------------------------------------------
       
   664 // From class MPSPropertyChangeObserver
       
   665 // Invoked when a TBuf8 type property is changed.
       
   666 // ---------------------------------------------------------------------------
       
   667 //
       
   668 void CPSServer::HandlePropertyChangeL( const TUid& /* aCategory */, 
       
   669                                        const TUint /*aKey*/, 
       
   670                                        const TPSTextProperty& /*aValue */ ){}
       
   671 
       
   672 // ---------------------------------------------------------------------------
       
   673 // From class MPSPropertyChangeObserver
       
   674 // Invoked when an error is encountered in property processing.
       
   675 // ---------------------------------------------------------------------------
       
   676 //
       
   677 void CPSServer::HandlePropertyChangeErrorL( const TUid& /* aCategory */, 
       
   678                                             const TUint /* aKey */, 
       
   679                                             TInt /*aError */){}
       
   680     
       
   681     
       
   682 
       
   683 // ======== GLOBAL FUNCTIONS ========
       
   684 
       
   685 // ---------------------------------------------------------------------------
       
   686 // Application entry point.
       
   687 // ---------------------------------------------------------------------------
       
   688 //
       
   689 TInt E32Main()
       
   690     {
       
   691     __UHEAP_MARK;
       
   692 
       
   693     TInt err = KErrNone;
       
   694 
       
   695     CTrapCleanup* cleanupStack = CTrapCleanup::New();
       
   696     if ( cleanupStack )
       
   697         {
       
   698         TRAP( err, InitServerL() )
       
   699 
       
   700         __ASSERT_DEBUG( !err, Panic( err ) );
       
   701         PSDEBUG( "CPSServer - Exiting" );
       
   702         delete cleanupStack;        
       
   703         }
       
   704     else
       
   705         {
       
   706         err = KErrNoMemory;
       
   707         }
       
   708         
       
   709     __UHEAP_MARKEND;
       
   710     
       
   711     return err;
       
   712     }
       
   713