gssettingsuis/Gs/GSFramework/src/GSWatchDog.cpp
branchRCL_3
changeset 54 7e0eff37aedb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gssettingsuis/Gs/GSFramework/src/GSWatchDog.cpp	Wed Sep 01 12:20:44 2010 +0100
@@ -0,0 +1,565 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+// INCLUDE FILES
+#include    <bldvariant.hrh>
+#include    <featmgr.h>
+#include    <centralrepository.h>
+
+// USER INCLUDES
+#include    "GSWatchDog.h"
+#include    "GsLogger.h"
+#include    "settingsinternalcrkeys.h"
+#include    "SettingsPrivateCRKeys.h"
+
+#include    <eikenv.h>
+#include    <s32mem.h>
+#include    <centralrepository.h>
+
+using namespace NCentralRepositoryConstants;
+
+// CONSTANTS
+
+
+// ========================= MEMBER FUNCTIONS ================================
+
+// ----------------------------------------------------------------------------
+// CGSWatchDog::NewL
+//
+// EPOC two-phased constructor
+// ----------------------------------------------------------------------------
+//
+CGSWatchDog* CGSWatchDog::NewL()
+    {
+    CGSWatchDog* self = new( ELeave ) CGSWatchDog;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CGSWatchDog::ConstructL
+//
+// EPOC default constructor can leave.
+// ----------------------------------------------------------------------------
+//
+void CGSWatchDog::ConstructL()
+    {
+    __GSLOGSTRING( "[CGSWatchDog] ConstructL()" );
+    iStore = CRepository::NewL( KCRUidMiscSettings );
+
+    // Read last stored state for watchdog...
+    ReadStateL();
+
+    // If GS crashed last time, activate watchdog, reset run counter. Watchdog
+    // will be active as long as exit was not clean (panicked).
+    if( !WasCleanExitL() &&
+        iWatchdogActivationLimit != KGSWatchdogActivationDisabled  )
+        {
+        iCrashCounter++;
+        iIsActive = ETrue;
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    #pragma message("-CGSWachDog verbose traces activated-")
+    User::InfoPrint( _L("Watchdog activated!") );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+
+        if( iQuarantine.Count() > 0 )
+            {
+            for( TInt i = 0; i < iQuarantine.Count(); i++ )
+                {
+                // If plugin is not already in blacklist, move it there from
+                // quarantinelist.
+                if( !IsInBlackList( iQuarantine[i] ) )
+                    {
+                    TGSPluginQuarantine quarantinedPlugin;
+                    quarantinedPlugin.iRunsAfterCrash = 0;
+                    quarantinedPlugin.iUid = iQuarantine[i];
+                    iBlackList.AppendL( quarantinedPlugin );
+                    iQuarantine.Remove( i );
+                    }
+                }
+            }
+        }
+     else
+        {
+        iIsActive = EFalse;
+        iCrashCounter = 0;
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    User::InfoPrint( _L("Watchdog disabled.") );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+
+        // Clean run -> empty quarantine.
+        iQuarantine.Reset();
+        }
+
+    // Continue normal progress, set application to run state...
+    iGSAppRunning = ETrue;
+
+    // Store watchdog state at this point as panic will not call normal
+    // destructors and data would be otherwise lost in case of panic.
+    StoreStateL();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::CGSWatchDog
+//
+// C++ constructor
+// ---------------------------------------------------------------------------
+CGSWatchDog::CGSWatchDog()
+    {
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::~CGSWatchDog
+//
+// Destructor
+// ---------------------------------------------------------------------------
+CGSWatchDog::~CGSWatchDog()
+    {
+    // Update all blacklisted plugins in case no crash FIRST, then store...
+    UpdateBlackListedPluginRunCounters();
+    TRAP_IGNORE( StoreStateL(); );
+    iBlackList.Close();
+    iQuarantine.Close();
+    delete iStore;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::Quarantine
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::QuarantineL( TUid aPluginUid )
+    {
+    if( iIsActive )
+        {
+        iQuarantine.AppendL( aPluginUid );
+        StoreQuarantineL(); // Store to persistent storage
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    __GSLOGSTRING1( "[CGSWatchDog] Quarantined:0x%X", aPluginUid.iUid );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::RemoveFromQuarantine
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::RemoveFromQuarantineL( TUid aPluginUid )
+    {
+    if( iIsActive )
+        {
+        for( TInt i = 0; i < iQuarantine.Count(); i++ )
+            {
+            if( iQuarantine[i] == aPluginUid )
+                {
+                iQuarantine.Remove( i );
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    __GSLOGSTRING1( "[CGSWatchDog] Removed from quarantine:0x%X", aPluginUid.iUid );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+
+                StoreQuarantineL();
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::WasCleanExit
+//
+//
+// ---------------------------------------------------------------------------
+TBool CGSWatchDog::WasCleanExitL()
+    {
+    return !iGSAppRunning;
+    }
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::ReportCleanExit
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::ReportCleanExitL()
+    {
+    iGSAppRunning = EFalse;
+    iStore->Set( KWatchDogGSRunning, iGSAppRunning );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::IsInBlackList
+//
+//
+// ---------------------------------------------------------------------------
+TBool CGSWatchDog::IsInBlackList( TUid aPluginUid )
+    {
+    TBool found = EFalse;
+    if( iIsActive )
+        {
+        for( TInt i = 0; i < iBlackList.Count(); i++ )
+            {
+            if( iBlackList[i].iUid == aPluginUid )
+                {
+                found = ETrue;
+                break;
+                }
+            }
+        }
+    
+    return found;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::StoreStateL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::StoreStateL()
+    {
+    //iStore->Set( KWatchDogIsActive,         iIsActive );
+    iStore->Set( KWatchDogGSRunning,        iGSAppRunning );
+    iStore->Set( KWatchDogCrashCounter,     iCrashCounter );
+    iStore->Set( KWatchdogActivationLimit,  iWatchdogActivationLimit );
+    iStore->Set( KWatchdogMaxPluginBlackListedRuns,   iMaxPluginBlackListedRuns );
+
+    StoreQuarantineL();
+    StoreBlackListL();
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    // The following is just for debug trace:
+    __GSLOGSTRING( "[CGSWatchDog] Storing state:" );
+    __GSLOGSTRING1( "   iIsActive: %d",     iIsActive );
+    __GSLOGSTRING1( "   iGSAppRunning: %d", iGSAppRunning );
+    __GSLOGSTRING1( "   iCrashCounter: %d",   iCrashCounter );
+    __GSLOGSTRING1( "   iWatchdogActivationLimit: %d", iWatchdogActivationLimit );
+    __GSLOGSTRING1( "   iMaxPluginBlackListedRuns: %d", iMaxPluginBlackListedRuns );
+
+    __GSLOGSTRING( "[CGSWatchDog] Stored plugins from quarantine:" );
+    for( TInt i = 0; i < iQuarantine.Count(); i++ )
+        {
+            __GSLOGSTRING1( "    0x%X", iQuarantine[i].iUid );
+        }
+    __GSLOGSTRING( "-" );
+
+    __GSLOGSTRING( "[CGSWatchDog] Stored plugins from blacklist:" );
+    for( TInt i = 0; i < iBlackList.Count(); i++ )
+        {
+            __GSLOGSTRING2( "    0x%X %d runs", iBlackList[i].iUid.iUid, iBlackList[i].iRunsAfterCrash );
+        }
+    __GSLOGSTRING( "-" );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::ReadStateL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::ReadStateL()
+    {
+    /*TInt isActive = EFalse; // Needed for mapping to TBool value
+    TInt err = iStore->Get( KWatchDogIsActive, isActive );
+    if( isActive == 1 )
+        {
+        iIsActive = ETrue;
+        }
+    else
+        {
+        iIsActive = EFalse;
+        }*/
+
+    TInt appRunning; // Needed for mapping to TBool value
+    TInt err = iStore->Get( KWatchDogGSRunning, appRunning );
+
+    if( err )
+        {
+        // CenRep values are uninitialized: first runtime of watchdog
+        // -> init values
+        InitStateL();
+        }
+
+    if( appRunning )
+        {
+        iGSAppRunning = ETrue;
+        }
+    else
+        {
+        iGSAppRunning = EFalse;
+        }
+
+    iStore->Get( KWatchDogCrashCounter, iCrashCounter );
+    iStore->Get( KWatchdogActivationLimit, iWatchdogActivationLimit );
+    iStore->Get( KWatchdogMaxPluginBlackListedRuns, iMaxPluginBlackListedRuns );
+
+    ReadQuarantineL();
+    ReadBlackListL();
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    // The following is just for debug trace:
+    __GSLOGSTRING( "[CGSWatchDog] Read state:" );
+    __GSLOGSTRING1( "   iIsActive: %d",     iIsActive );
+    __GSLOGSTRING1( "   iGSAppRunning: %d", iGSAppRunning );
+    __GSLOGSTRING1( "   iCrashCounter: %d", iCrashCounter );
+    __GSLOGSTRING1( "   iWatchdogActivationLimit: %d", iWatchdogActivationLimit );
+    __GSLOGSTRING1( "   iMaxPluginBlackListedRuns: %d", iMaxPluginBlackListedRuns );
+
+    __GSLOGSTRING( "[CGSWatchDog] Read plugins from quarantine:" );
+    for( TInt i = 0; i < iQuarantine.Count(); i++ )
+        {
+            __GSLOGSTRING1( "    0x%X", iQuarantine[i].iUid );
+        }
+    __GSLOGSTRING( "-" );
+
+    __GSLOGSTRING( "[CGSWatchDog] Read plugins from blacklist:" );
+    for( TInt i = 0; i < iBlackList.Count(); i++ )
+        {
+            __GSLOGSTRING2( "    0x%X %d runs", iBlackList[i].iUid.iUid, iBlackList[i].iRunsAfterCrash );
+        }
+    __GSLOGSTRING( "-" );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::InitStateL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::InitStateL()
+    {
+    __GSLOGSTRING( "[CGSWatchDog] initializing state..." );
+    iIsActive = EFalse;
+    iGSAppRunning = EFalse;
+    iCrashCounter = 0;
+
+    // Check CenRep, if values do not exist, use default values:
+    TInt err;
+    err = iStore->Get( KWatchDogCrashCounter, iWatchdogActivationLimit );
+    if( err )
+        {
+        iWatchdogActivationLimit = KGSDefaultWatchdogActivationLimit;
+        }
+
+    err = iStore->Get( KWatchdogMaxPluginBlackListedRuns, iMaxPluginBlackListedRuns);
+    if( err )
+        {
+        iMaxPluginBlackListedRuns = KGSDefaultMaxPluginBlackListedRuns;
+        }
+
+    StoreStateL();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::ReadQuarantineL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::ReadQuarantineL()
+    {
+    HBufC8* buf = HBufC8::NewLC( KMaxBinaryLength );
+    TPtr8 serializedArr = buf->Des();
+    iStore->Get( KWatchDogQuarantine, serializedArr );
+    RDesReadStream stream;
+    stream.Open( serializedArr );
+    CleanupClosePushL( stream );
+
+    // In case CenRep value is uninitialized (less than 16 bits), don't try
+    //reading it
+    TInt count = 0;
+    if( buf->Size() > 0 )
+        {
+        count = stream.ReadUint16L();
+        }
+    for( TInt i = 0; i < count; i++  )
+        {
+        TUid uid;
+        uid.iUid = stream.ReadInt32L();
+        iQuarantine.AppendL( uid );
+        }
+    //stream.Close();
+    CleanupStack::PopAndDestroy( &stream );
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::StoreQuarantineL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::StoreQuarantineL()
+    {
+    // Hmmm. KMaxBinaryLength = 1024*2 unicode characters (16bit)
+    // = 1024*2*16 bits = 32768.
+    // 32768 - 16(count) bits reserved for 32 bit TUids = 1023.5 TUids
+    // -> We can store 1023 UIds in quarantine. Should be enought as we have
+    // about ~50 plugins at the moment and each plugin ought to be listed in
+    // quarantine only once at a specific point of time.
+    HBufC8* buf = HBufC8::NewLC( KMaxBinaryLength );
+    TPtr8 serializedArr = buf->Des();
+    RDesWriteStream stream;
+    stream.Open( serializedArr );
+    CleanupClosePushL( stream );
+
+    stream.WriteUint16L( iQuarantine.Count() );
+
+    for( TInt i = 0; i < iQuarantine.Count(); i++ )
+        {
+        stream.WriteInt32L( iQuarantine[i].iUid );
+        }
+    // This also flushes the stream:
+    CleanupStack::PopAndDestroy( &stream );
+
+    iStore->Set( KWatchDogQuarantine, serializedArr );
+
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::ReadBlackListL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::ReadBlackListL()
+    {
+    HBufC8* buf = HBufC8::NewLC( KMaxBinaryLength );
+    TPtr8 serializedArr = buf->Des();
+    iStore->Get( KWatchDogBlackList, serializedArr );
+    RDesReadStream stream;
+    stream.Open( serializedArr );
+    CleanupClosePushL( stream );
+
+    // In case CenRep value is uninitialized (less than 16 bits), don't try
+    //reading it
+    TInt count = 0;
+    if( buf->Size() > 0 )
+        {
+        count = stream.ReadUint16L();
+        }
+    for( TInt i = 0; i < count; i++  )
+        {
+        TGSPluginQuarantine plugin;
+        plugin.InternalizeL( stream );
+        iBlackList.AppendL( plugin );
+        }
+
+    //stream.Close();
+    CleanupStack::PopAndDestroy( &stream );
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::StoreBlackListL
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::StoreBlackListL()
+    {
+    HBufC8* buf = HBufC8::NewLC( KMaxBinaryLength );
+    TPtr8 serializedArr = buf->Des();
+    RDesWriteStream stream;
+    stream.Open( serializedArr );
+    CleanupClosePushL( stream );
+
+    stream.WriteUint16L( iBlackList.Count() );
+
+    for( TInt i = 0; i < iBlackList.Count(); i++ )
+        {
+        iBlackList[i].ExternalizeL( stream );
+
+#ifdef _GS_WATCHDOG_VERBOSE_TRACES
+    __GSLOGSTRING1( "[CGSWatchDog] Written to blacklist 0x%X",
+                    iBlackList[i].iUid.iUid );
+#endif //_GS_WATCHDOG_VERBOSE_TRACES
+
+        }
+    // This also flushes the stream:
+    CleanupStack::PopAndDestroy( &stream );
+
+    iStore->Set( KWatchDogBlackList, serializedArr );
+
+    CleanupStack::PopAndDestroy( buf );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGSWatchDog::UpdateBlackListedPluginRunCounters
+//
+//
+// ---------------------------------------------------------------------------
+void CGSWatchDog::UpdateBlackListedPluginRunCounters()
+    {
+    TInt count = iBlackList.Count();
+    for( TInt i = 0; i < count; i++ )
+        {
+        iBlackList[i].iRunsAfterCrash++;
+        if( iBlackList[i].iRunsAfterCrash > iMaxPluginBlackListedRuns )
+            {
+//__GSLOGSTRING2( "[CGSWatchDog] 0x%X removed from blacklist (%d runs)", iBlackList[i].iUid.iUid, iBlackList[i].iRunsAfterCrash );
+            iBlackList.Remove( i );
+            i--;    // Item in index i has been removed
+            count--;// One item has been removed from the array
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// TGSPluginQuarantine::InternalizeL
+//
+//
+// ---------------------------------------------------------------------------
+void TGSPluginQuarantine::InternalizeL( RReadStream& aStream )
+    {
+    iUid.iUid = aStream.ReadInt32L();
+    iRunsAfterCrash = aStream.ReadInt16L();
+    }
+
+
+// ---------------------------------------------------------------------------
+// TGSPluginQuarantine::ExternalizeL
+//
+//
+// ---------------------------------------------------------------------------
+void TGSPluginQuarantine::ExternalizeL( RWriteStream& aStream ) const
+    {
+    aStream.WriteInt32L( iUid.iUid );
+    aStream.WriteInt16L( iRunsAfterCrash );
+    }
+
+
+//End of File