sysresmonitoring/oommonitor/src/oomconfigparser.cpp
author William Roberts <williamr@symbian.org>
Fri, 23 Apr 2010 14:37:17 +0100
branchRCL_3
changeset 22 c82a39b81a38
parent 12 7645e9ce10dc
child 58 0818dd463d41
permissions -rw-r--r--
Rework addition of Symbian splash screen to reduce the source impact (uses SVG from Bug 2414) Notes: by using the OPTION SOURCEDIR parameter in the mifconv extension instructions, I can arrange to use the same source file name in sfimage, without having to export over the original Nokia file. This means that the name inside splashscreen.mbg is the same, which removes the need for the conditional compilation in SplashScreen.cpp, and gets rid of sf_splashscreen.mmp.

/*
* Copyright (c) 2006 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:  The parser for the OOM configuration file.
*
*/
#include <e32base.h>
#include <xml/parser.h>

#include "oomconfigparser.h"
#include "oompanic.h"
#include "OomTraces.h"
#include "oomidletimerule.h"
#include "oomforegroundrule.h"
#include "oomconstants.hrh"
#include "oomapplicationconfig.h"
#include "oomcloseappconfig.h"
#include "oomconfig.h"
#include "oomrunpluginconfig.h"

enum TOomConfigParserPanic
{
KOomErrMoreThanOneOomConfig = 0,
KOomErrGlobalSettingsMustComeAfterRoot,
KOomErrAppSettingsMustComeAfterGlobalSettings,
KOomErrCloseAppSettingsMustComeAfterAppSettings,
KOomErrAppIdleSettingsMustComeAfterAppCloseSettings,
KOomErrLowRamErrorInGlobalSettings,
KOomErrGoodRamErrorInGlobalSettings,
KOomErrMaxCloseErrorInGlobalSettings,
KOomErrDefaultPriorityErrorInGlobalSettings,
KOomErrMissingUidFromAppCloseConfig,
KOomErrMissingPriorityFromAppCloseConfig,
KOomErrMissingSyncModeFromAppCloseConfig,
KOomErrMissingEstimateFromAppCloseConfig,
KOomErrInvalidSyncMode,
KOomErrMissingSyncModeInAppCloseConfig,
KOomErrBadOrMissingPriorityInAppIdleRule,
KOomErrBadOrMissingIdleTimeInAppIdleRule,
KOomErrBadOrMissingUidInAppIdleRule,
KOomErrBadNeverCloseValue,
KOomErrBadOrMissingUidInAppConfig,
KOomErrBadOrMissingPriorityInAppCloseConfig,
KOomErrBadLowThresholdValueForAppConfig,
KOomErrBadGoodThresholdValueForAppConfig,
KOomErrSystemPluginSettingsMustComeAfterAppCloseSettings,
KOomErrAppPluginSettingsMustComeAfterSystemPluginSettings,
KOomErrAppPluginIdleTimeRulesMustComeAfterAppPluginSettings,
KOomErrBadOrMissingUidInAppCloseConfig,
KOomErrBadOrMissingUidInSystemPluginConfig,
KOomErrBadOrMissingPriorityInSystemPluginConfig,
KOomErrBadOrMissingTargetAppIdInAppPluginConfig,
KOomErrBadOrMissingUidInAppPluginConfig,
KOomErrBadOrMissingPriorityInAppPluginConfig,
KOomErrBadOrMissingPriorityInPluginIdleRule,
KOomErrBadOrMissingIdleTimeInPluginIdleRule,
KOomErrBadOrMissingUidInPluginIdleRule,
KOomErrBadOrMissingUidInForegroundAppRule,
KOomErrBadOrMissingPriorityInForegroundAppRule,
KOomErrBadOrMissingTargetAppIdInForegroundAppRule,
KOomErrDefaultWaitAfterPluginInGlobalSettings,
KOomErrBadOrMissingPriorityInForceCheck,
KOomErrOomRulesMustComeLast,
KOomErrBadPluginWaitTime,
KOomErrBadXml,
KOomErrAppCloseIdleRuleOutsideAppCloseElement,
KOomErrForegroundAppRuleOutsideAppCloseElement,
KOomErrPluginIdleRuleOutsideAppPluginElement,
KOomErrPluginForegroundRuleOutsidePluginElement,
KOomErrBadCallIfTargetAppNotRunning
};

const TInt KOomXmlFileBufferSize = 1024;
const TInt KOomMaxAppExitTime = 2000;
const TInt KBytesInMegabyte = 1024;
#ifdef __WINS__
const TInt KEmulatorTickDivisor = 5; // The tick is 5 times slower on the emulator than on the phone
#endif
using namespace Xml;

// Mime type of the parsed document
_LIT8(KXmlMimeType, "text/xml");

_LIT(KOomConfigFilePath, ":\\private\\10207218\\oomconfig.xml");
_LIT(KRomDrive, "z");

// Element strings
// Root
_LIT8(KOomConfigOomConfig, "oom_config");

// Global settings
_LIT8(KOomConfigGlobalSettings, "global_settings");
_LIT8(KOomConfigForceCheckAtPriority, "force_check");

// App settings
_LIT8(KOomConfigAppSettings, "app_specific_thresholds");
_LIT8(KOomConfigApp, "app");

// App close settings
_LIT8(KOomConfigAppCloseSettings, "app_close_settings");
_LIT8(KOomConfigCloseApp, "close_app");

// App close idle time
_LIT8(KOomConfigAppCloseIdlePriority, "app_close_idle_priority");

_LIT8(KOomConfigForegroundAppPriority, "foreground_app_priority");

// Global settings attribute names
_LIT8(KOomAttributeLowRamThreshold, "low_ram_threshold");
_LIT8(KOomAttributeGoodRamThreshold, "good_ram_threshold");
_LIT8(KOomAttributeMaxAppCloseBatch, "max_app_close_batch");
_LIT8(KOomAttributeDefaultWaitAfterPlugin, "default_wait_after_plugin");
_LIT8(KOomAttributeMaxAppExitTime , "max_app_exit_time");

// System plugins 

_LIT8(KOomAttributeSystemPluginSettings, "system_plugin_settings");
_LIT8(KOomAttributeSystemPlugin, "system_plugin");

// Application plugins

_LIT8(KOomAttributeAppPluginSettings, "app_plugin_settings");
_LIT8(KOomAttributeAppPlugin, "app_plugin");

// Plugin idle time rules

_LIT8(KOomAttributePluginIdlePriority, "plugin_idle_priority");

// Plugin foreground app rules
_LIT8(KOomAttributePluginForegroundAppPriority, "plugin_foreground_app_priority");

// Atribute names
_LIT8(KOomAttibuteUid, "uid");
_LIT8(KOomAttibuteSyncMode, "sync_mode");
_LIT8(KOomAttibutePriority, "priority");
_LIT8(KOomAttibuteRamEstimate, "ram_estimate");

_LIT8(KOomConfigSyncModeContinue, "continue");
_LIT8(KOomConfigSyncModeCheck, "check");
_LIT8(KOomConfigSyncModeEstimate, "estimate");

_LIT8(KOomAttibuteIdleTime, "idle_time");
_LIT8(KOomAttibuteIdlePriority, "priority");

_LIT8(KOomAttibuteNeverClose, "NEVER_CLOSE");

_LIT8(KOomAttributeTargetAppId, "target_app_id");

_LIT8(KOomAttributeWait, "wait");

_LIT8(KOomAttributeIfForegroundAppId, "if_foreground_app_id");

_LIT8(KOomAttributeCallIfTargetAppNotRunning, "call_if_target_app_not_running");
_LIT8(KOomAttributeTrue, "true");
_LIT8(KOomAttributeFalse, "false");
_LIT8(KOomAttribute0, "0");
_LIT8(KOomAttribute1, "1");


_LIT8(KOomConfigDefaultAppUid, "DEFAULT_APP");
_LIT8(KOomConfigDefaultPluginUid, "DEFAULT_PLUGIN");
_LIT8(KOomConfigTargetAppValue, "TARGET_APP");

_LIT8(KOomConfigBusyAppUid, "BUSY_APP");
_LIT8(KOomConfigHighPriorityAppUid, "HIGH_PRIORITY_APP");

COomConfigParser::COomConfigParser(COomConfig& aConfig, RFs& aFs) : iConfig(aConfig), iFs(aFs), iState(EOomParsingStateNone)
    {
    }

void COomConfigParser::ParseL()
    {
    FUNC_LOG;

    TRACES("COomConfigParser::ParseL: Parsing Config File");
    
    CParser* parser = CParser::NewLC(KXmlMimeType, *this);
    
    RFile configFile;
    TFileName configFileName;
    TChar driveChar = iFs.GetSystemDriveChar();
    configFileName.Append(driveChar);
    configFileName.Append(KOomConfigFilePath);
    if (configFile.Open(iFs, configFileName, EFileShareExclusive) != KErrNone)
        {
        configFileName.Replace(0,1,KRomDrive); //replace 'c' with 'z'
        User::LeaveIfError(configFile.Open(iFs, configFileName, EFileShareExclusive));
        }
    CleanupClosePushL(configFile);
    
    TBuf8<KOomXmlFileBufferSize> fileBuffer;
    TInt bytesRead;
    do
        {
        User::LeaveIfError(configFile.Read(fileBuffer));
        bytesRead = fileBuffer.Size();
        
        parser->ParseL(fileBuffer);
        
        } while (bytesRead != 0);
    
    CleanupStack::PopAndDestroy(2, parser); // config file - automatically closes it
                                            // parser
            
    TRACES("COomConfigParser::ParseL: Finished Parsing Config File");    
    }

void COomConfigParser::OnStartDocumentL(const RDocumentParameters&, TInt)
    {
    FUNC_LOG;
    }

void COomConfigParser::OnEndDocumentL(TInt)
    {
    FUNC_LOG;
    }


void COomConfigParser::OnEndElementL(const RTagInfo&, TInt)
    {
    }

void COomConfigParser::OnContentL(const TDesC8&, TInt)
    {
    }

void COomConfigParser::OnStartPrefixMappingL(const RString&, const RString&, 
                                   TInt)
    {
    }

void COomConfigParser::OnEndPrefixMappingL(const RString&, TInt)
    {
    }

void COomConfigParser::OnIgnorableWhiteSpaceL(const TDesC8&, TInt)
    {
    }

void COomConfigParser::OnSkippedEntityL(const RString&, TInt)
    {
    }

void COomConfigParser::OnProcessingInstructionL(const TDesC8&, const TDesC8&, 
                                      TInt)
    {
    }

void COomConfigParser::OnError(TInt)
    {
    }

TAny* COomConfigParser::GetExtendedInterface(const TInt32)
    {
    return 0;
    }

void COomConfigParser::OnStartElementL(const RTagInfo& aElement, const RAttributeArray& aAttributes, 
                             TInt aErrorCode)
    {
    if (aErrorCode != KErrNone)
        ConfigError(KOomErrBadXml);
    
    StartElementL(aElement.LocalName().DesC(), aAttributes);
    }

void COomConfigParser::StartElementL(const TDesC8& aLocalName,
                                        const RAttributeArray& aAttributes)
    {
    // Root
    if (aLocalName == KOomConfigOomConfig)
        {
        if (iState != EOomParsingStateNone)
            ConfigError(KOomErrMoreThanOneOomConfig);
        
        ChangeState(EOomParsingStateRoot);
        }
    // Parse main elements
    else if (aLocalName == KOomConfigGlobalSettings)
        {
        if (iState != EOomParsingStateRoot)
            ConfigError(KOomErrGlobalSettingsMustComeAfterRoot);
        
        SetGlobalSettings(aAttributes);
        
        ChangeState(EOomParsingStateGlobalSettings);
        }
    else if (aLocalName == KOomConfigAppSettings)
        {
        ChangeState(EOomParsingStateAppSettings);
        }
    else if (aLocalName == KOomConfigAppCloseSettings)
        {
        ChangeState(EOomParsingStateAppCloseSettings);
        }
    else if (aLocalName == KOomAttributeSystemPluginSettings)
        {
        ChangeState(EOomParsingStateSystemPluginSettings);
        }
    else if (aLocalName == KOomAttributeAppPluginSettings)
        {
        ChangeState(EOomParsingStateAppPluginSettings);
        }
    // Parse actual configuration elements
    else if (aLocalName == KOomConfigForceCheckAtPriority)
        {
        SetForceCheckConfigL(aAttributes);
        }
    else if (aLocalName == KOomConfigApp)
        {
        SetAppConfigL(aAttributes);
        }
    else if (aLocalName == KOomConfigCloseApp)
        {
        SetCloseAppConfigL(aAttributes);
        }
    else if (aLocalName == KOomConfigAppCloseIdlePriority)
        {
        CheckState(EOomParsingStateAppCloseSettings, KOomErrAppCloseIdleRuleOutsideAppCloseElement);
        SetAppCloseIdlePriorityConfigL(aAttributes);
        }
    else if (aLocalName == KOomConfigForegroundAppPriority)
        {
        CheckState(EOomParsingStateAppCloseSettings, KOomErrForegroundAppRuleOutsideAppCloseElement);
        SetForegroundAppPriorityL(aAttributes);
        }
    else if (aLocalName == KOomAttributeSystemPlugin)
        {
        SetSystemPluginConfigL(aAttributes);
        }
    else if (aLocalName == KOomAttributeAppPlugin)
        {
        SetAppPluginConfigL(aAttributes);
        }
    else if (aLocalName == KOomAttributePluginIdlePriority)
        {
        CheckState(EOomParsingStateAppPluginSettings, KOomErrPluginIdleRuleOutsideAppPluginElement);
        SetPluginIdlePriorityL(aAttributes);
        }
    else if (aLocalName == KOomAttributePluginForegroundAppPriority)
        {
        CheckState(EOomParsingStateAppPluginSettings, EOomParsingStateSystemPluginSettings, KOomErrPluginForegroundRuleOutsidePluginElement);
        SetPluginForegroundAppPriorityL(aAttributes);
        }
    
    }

void COomConfigParser::ConfigError(TInt aError)
    {
    OomConfigParserPanic(aError);
    }

void COomConfigParser::SetGlobalSettings(const RAttributeArray& aAttributes)
    {
    TInt defaultLowMemoryThreshold;    
    TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeLowRamThreshold, defaultLowMemoryThreshold);

    if (err == KErrNone)
        iConfig.SetDefaultLowRamThreshold(defaultLowMemoryThreshold * KBytesInMegabyte);
    else
        ConfigError(KOomErrLowRamErrorInGlobalSettings);
    
    if (err == KErrNone)
        {
        TInt defaultGoodMemoryThreshold;    
        TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeGoodRamThreshold, defaultGoodMemoryThreshold);

        if (err == KErrNone)
            iConfig.SetDefaultGoodRamThreshold(defaultGoodMemoryThreshold * KBytesInMegabyte);
        else
            ConfigError(KOomErrGoodRamErrorInGlobalSettings);
        }

    if (err == KErrNone)
        {
        TInt defaultMaxCloseAppBatch;    
        TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeMaxAppCloseBatch, defaultMaxCloseAppBatch);

        if (err == KErrNone)
            iConfig.SetMaxCloseAppBatch(defaultMaxCloseAppBatch);
        else
            ConfigError(KOomErrMaxCloseErrorInGlobalSettings);
        }
    
    if (err == KErrNone)
        {
        TInt defaultWaitAfterPlugin;    
        TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeDefaultWaitAfterPlugin, defaultWaitAfterPlugin);

        if (err == KErrNone)
            iConfig.SetDefaultWaitAfterPlugin(defaultWaitAfterPlugin);
        else
            ConfigError(KOomErrDefaultWaitAfterPluginInGlobalSettings);
        }
    
    if (err == KErrNone)
        {
        TInt maxAppExitTime;    
        TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeMaxAppExitTime, maxAppExitTime);

        if (err == KErrNone)
            iConfig.SetMaxAppExitTime(maxAppExitTime);
        else
            iConfig.SetMaxAppExitTime(KOomMaxAppExitTime);
        }
    }

void COomConfigParser::SetForceCheckConfigL(const RAttributeArray& aAttributes)
    {
    TUint priority;
    TInt err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibutePriority, priority);
    if (err == KErrNone)
        {
        iConfig.GlobalConfig().AddForceCheckPriorityL(priority);
        }
    else
        {
        ConfigError(KOomErrBadOrMissingPriorityInForceCheck);    
        }
    }

void COomConfigParser::SetAppConfigL(const RAttributeArray& aAttributes)
    {
    TUint uid;
    COomApplicationConfig* appConfig = NULL;
    
    TInt err = GetValueFromHexAttributeList(aAttributes, KOomAttibuteUid, uid);
    
    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingUidInAppConfig);
        }
    else
        iParentUid = uid;

    appConfig = COomApplicationConfig::NewL(uid);
    CleanupStack::PushL(appConfig);    
        
    // Set the app specific memory thresholds (if they exist)
    // Get the app specific low threshold
    if (err == KErrNone)
        {
        TUint lowThreshold;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeLowRamThreshold, lowThreshold);
        if (err == KErrNone)
            {
            appConfig->iLowRamThreshold = lowThreshold * KBytesInMegabyte;
            }
        else if (err == KErrNotFound)
            err = KErrNone;
        
        if (err != KErrNone)
            ConfigError(KOomErrBadLowThresholdValueForAppConfig);
        }

    // Get the app specific good threshold
    if (err == KErrNone)
        {
        TUint goodThreshold;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeGoodRamThreshold, goodThreshold);
        if (err == KErrNone)
            {
            appConfig->iGoodRamThreshold = goodThreshold * KBytesInMegabyte;
            }
        else if (err == KErrNotFound)
            err = KErrNone;
        
        if (err != KErrNone)
            ConfigError(KOomErrBadGoodThresholdValueForAppConfig);
        }
    
    // Add the applciation config to the main config
    if ((err == KErrNone) && (appConfig))
        {
        iConfig.AddApplicationConfigL(appConfig);
        }
    
    if (appConfig)
        CleanupStack::Pop(appConfig);
    }

void COomConfigParser::SetCloseAppConfigL(const RAttributeArray& aAttributes)
    {
    // Get and convert uid attribute to TInt
    TInt err = KErrNone;
    
    TUint uid;
    err = GetValueFromHexAttributeList(aAttributes, KOomAttibuteUid, uid);

    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingUidInAppCloseConfig);    
        return;
        }
    else
        iParentUid = uid;
    
    COomCloseAppConfig* closeAppConfig = COomCloseAppConfig::NewL(uid); // Radio UID
    CleanupStack::PushL(closeAppConfig);

     if (err == KErrNone)
        {
        // Check that we have a priority for the added app_close event
        // Specifying a priority is mandatory
        TUint priority;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibutePriority, priority);
        if (err == KErrNone)
            {
            closeAppConfig->SetDefaultPriority(priority);
            }
        else
            {
            ConfigError(KOomErrBadOrMissingPriorityInAppCloseConfig);    
            }
        }
    
    if (err == KErrNone)
        {
        TPtrC8 syncModeString;
        err = GetValueFromAttributeList(aAttributes, KOomAttibuteSyncMode, syncModeString);
        
        if (err == KErrNone)
            {
            TOomSyncMode syncMode = EContinue;
            
            if (syncModeString == KOomConfigSyncModeContinue)
                syncMode = EContinue;
            else if (syncModeString == KOomConfigSyncModeCheck)
                syncMode = ECheckRam;
            else if (syncModeString == KOomConfigSyncModeEstimate)
                syncMode = EEstimate;
            else
                ConfigError(KOomErrInvalidSyncMode);
            
            if (err == KErrNone)
                {
                closeAppConfig->iSyncMode = syncMode;
                }
            }
        else
            {
            ConfigError(KOomErrMissingSyncModeInAppCloseConfig);
            }
        }
    
    
    if (err == KErrNone)
        {
        // If we have a default priority attribute then add it, otherwise use the global default priority
        TInt ramEstimate;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteRamEstimate, ramEstimate);
        if ((err == KErrNotFound) && (closeAppConfig->iSyncMode != EEstimate))
            {
            err = KErrNone;
            }
        
        if (err != KErrNone)
            ConfigError(KOomErrMissingEstimateFromAppCloseConfig);
        else
            closeAppConfig->iRamEstimate = ramEstimate * KBytesInMegabyte;
           }

    if (err == KErrNone)
        iConfig.SetAppCloseConfigL(closeAppConfig);
    
    CleanupStack::Pop(closeAppConfig);
    }

void COomConfigParser::SetAppCloseIdlePriorityConfigL(const RAttributeArray& aAttributes)
    {
    TUint uid;
    TInt idleTime;
    TUint priority;

    // Use the UID from the parent scope
    uid = iParentUid;

    TInt err = KErrNone;
    
    err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdleTime, idleTime);
    
#ifdef __WINS__
    // The tick is 5 times slower on the emulator than on the phone
    idleTime = idleTime / KEmulatorTickDivisor;
#endif
    
    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingIdleTimeInAppIdleRule);
        }
    
    if (err == KErrNone)
        {
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdlePriority, priority);
        
        if (err != KErrNone)
            {
            ConfigError(KOomErrBadOrMissingPriorityInAppIdleRule);
            }
        }
    
    if (err == KErrNone)
        {
        COomIdleTimeRule* idleRule = COomIdleTimeRule::NewL(idleTime, priority);
        CleanupStack::PushL(idleRule);
        iConfig.AddApplicationRuleL(uid, idleRule);
        CleanupStack::Pop(idleRule);
        }
    }

void COomConfigParser::SetForegroundAppPriorityL(const RAttributeArray& aAttributes)
    {
    TUint appUid;
    TUint targetAppId;
    TUint priority;

    TInt err = KErrNone;
    
    // Use the UID from the parent scope
    appUid = iParentUid;

    // Check that we have a priority for the added system plugin action
    // Specifying a priority is mandatory
    err = GetValueFromHexAttributeList(aAttributes, KOomAttributeIfForegroundAppId, targetAppId);
    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingTargetAppIdInForegroundAppRule);    
        }
    
    if (err == KErrNone)
        {
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdlePriority, priority);
        
        if (err != KErrNone)
            {
            ConfigError(KOomErrBadOrMissingPriorityInForegroundAppRule);
            }
        }
    
    if (err == KErrNone)
        {
        COomForegroundRule* foregroundRule = new (ELeave) COomForegroundRule(targetAppId, priority);
        CleanupStack::PushL(foregroundRule);
        iConfig.AddApplicationRuleL(appUid, foregroundRule);
        CleanupStack::Pop(foregroundRule);
        }

    }

void COomConfigParser::SetSystemPluginConfigL(const RAttributeArray& aAttributes)
    {
    // Get and convert uid attribute to TInt
    TInt err = KErrNone;
    
    TUint uid;
    err = GetValueFromHexAttributeList(aAttributes, KOomAttibuteUid, uid);

    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingUidInSystemPluginConfig);    
        return;
        }
    else
        iParentUid = uid;
    
    COomRunPluginConfig* pluginConfig = COomRunPluginConfig::NewL(uid, EOomSystemPlugin);
    CleanupStack::PushL(pluginConfig);

     if (err == KErrNone)
        {
        // Check that we have a priority for the added system plugin action
        // Specifying a priority is mandatory
        TUint priority;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibutePriority, priority);
        if (err == KErrNone)
            {
            pluginConfig->SetDefaultPriority(priority);
            }
        else
            {
            ConfigError(KOomErrBadOrMissingPriorityInSystemPluginConfig);    
            }
        }
     
     if (err == KErrNone)
        {
        TInt wait;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeWait, wait);
        if (err == KErrNone)
            {
            pluginConfig->SetWaitAfterPlugin(wait);
            }
        else if (err == KErrNotFound)
            {
            // If this attribute isn't present then just don't set it, and clear the error
            err = KErrNone;
            }
        else
            ConfigError(KOomErrBadPluginWaitTime);
        }
     
     if (err == KErrNone)
         {
         // Get the config for the sync mode for this plugin (if one is specified) and set it
         SetPluginSyncMode(aAttributes, *pluginConfig);
         }

     iConfig.AddPluginConfigL(pluginConfig);
     
     CleanupStack::Pop(pluginConfig);
    }

void COomConfigParser::SetAppPluginConfigL(const RAttributeArray& aAttributes)
    {
    // Get and convert uid attribute to TInt
    TInt err = KErrNone;
    
    TUint uid;
    err = GetValueFromHexAttributeList(aAttributes, KOomAttibuteUid, uid);

    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingUidInAppPluginConfig);    
        return;
        }
    else
        iParentUid = uid;
    
    COomRunPluginConfig* pluginConfig = COomRunPluginConfig::NewL(uid, EOomAppPlugin);
    CleanupStack::PushL(pluginConfig);

    if (err == KErrNone)
       {
       // Check that we have a priority for the added system plugin action
       // Specifying a priority is mandatory
        TUint priority;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibutePriority, priority);
        if (err == KErrNone)
            {
            pluginConfig->SetDefaultPriority(priority);
            }
        else
            {
            ConfigError(KOomErrBadOrMissingPriorityInAppPluginConfig);    
            }
       }

    if (err == KErrNone)
       {
       // Check that we have a priority for the added system plugin action
       // Specifying a priority is mandatory
        TUint targetAppId;
        err = GetValueFromHexAttributeList(aAttributes, KOomAttributeTargetAppId, targetAppId);
        if (err == KErrNone)
            {
            pluginConfig->SetTargetApp(targetAppId);
            iParentTargetApp = targetAppId;
            }
        else
            {
            ConfigError(KOomErrBadOrMissingTargetAppIdInAppPluginConfig);    
            }
       }
    
    if (err == KErrNone)
       {
       TInt wait;
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttributeWait, wait);
        if (err == KErrNone)
            {
            pluginConfig->SetWaitAfterPlugin(wait);
            }
        else if (err == KErrNotFound)
            {
            // If this attribute isn't present then just don't set it, and clear the error
            err = KErrNone;
            }
        else
            ConfigError(KOomErrBadPluginWaitTime);
       }    
    
    if (err == KErrNone)
        {
        // Get the config for the sync mode for this plugin (if one is specified) and set it
        SetPluginSyncMode(aAttributes, *pluginConfig);
        
        TBool targetAppNotRunning;
        err = GetValueFromBooleanAttributeList(aAttributes, KOomAttributeCallIfTargetAppNotRunning, targetAppNotRunning);
        if (err == KErrNone)
            {
            pluginConfig->SetCallIfTargetAppNotRunning(targetAppNotRunning);
            }
        else if (err == KErrNotFound)
            {
            // If this attribute isn't present then just don't set it, and clear the error
            err = KErrNone;
            }
        else
            {
            ConfigError(KOomErrBadCallIfTargetAppNotRunning);
            }
        }

     iConfig.AddPluginConfigL(pluginConfig);
     
     CleanupStack::Pop(pluginConfig);

    }

void COomConfigParser::SetPluginIdlePriorityL(const RAttributeArray& aAttributes)
    {
    TUint uid;
    TInt idleTime;
    TUint priority;

    TInt err = KErrNone;
    
    // Use the UID from the parent scope
    uid = iParentUid;

    err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdleTime, idleTime);
    
#ifdef __WINS__
    // The tick is 5 times slower on the emulator than on the phone
    idleTime = idleTime / KEmulatorTickDivisor;
#endif
    
    if (err != KErrNone)
        {
        ConfigError(KOomErrBadOrMissingIdleTimeInPluginIdleRule);
        }
    
    if (err == KErrNone)
        {
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdlePriority, priority);
        
        if (err != KErrNone)
            {
            ConfigError(KOomErrBadOrMissingPriorityInPluginIdleRule);
            }
        }
    
    if (err == KErrNone)
        {
        COomIdleTimeRule* idleRule = COomIdleTimeRule::NewL(idleTime, priority);
        CleanupStack::PushL(idleRule);
        iConfig.AddPluginRuleL(uid, idleRule);
        CleanupStack::Pop(idleRule);
        }
    }

void COomConfigParser::SetPluginForegroundAppPriorityL(const RAttributeArray& aAttributes)
    {
    TUint uid;
    TUint targetAppId;
    TUint priority;

    TInt err = KErrNone;
    
    // Use the UID from the parent scope
    uid = iParentUid;

        // Check that we have a priority for the added system plugin action
        // Specifying a priority is mandatory
        
    TPtrC8 targetAppString;
    err = GetValueFromAttributeList(aAttributes, KOomAttributeTargetAppId, targetAppString);
    if ((err == KErrNone)
            && (targetAppString == KOomConfigTargetAppValue)
            && (iState == EOomParsingStateAppPluginSettings))
        // If the target app is specified as "TARGET_APP" then we use the target app from the parent entry
        {
        targetAppId = iParentTargetApp;
        }
    else
        {
        err = GetValueFromHexAttributeList(aAttributes, KOomAttributeTargetAppId, targetAppId);
        if (err != KErrNone)
            {
            ConfigError(KOomErrBadOrMissingTargetAppIdInForegroundAppRule);    
            }
        }
     
    if (err == KErrNone)
        {
        err = GetValueFromDecimalAttributeList(aAttributes, KOomAttibuteIdlePriority, priority);
        
        if (err != KErrNone)
            {
            ConfigError(KOomErrBadOrMissingPriorityInForegroundAppRule);
            }
        }
    
    if (err == KErrNone)
        {
        COomForegroundRule* foregroundRule = new (ELeave) COomForegroundRule(targetAppId, priority);
        CleanupStack::PushL(foregroundRule);
        iConfig.AddPluginRuleL(uid, foregroundRule);
        CleanupStack::Pop(foregroundRule);
        }
    }

// Finds an attribute of the given name and gets its value
// A value is only valid as long as AAtrributes is valid (and unmodified)
// Returns KErrNone if the attribute is present in the list, KErrNotFound otherwise
TInt COomConfigParser::GetValueFromAttributeList(const RAttributeArray& aAttributes, const TDesC8& aName, TPtrC8& aValue)
    {
    TInt index = aAttributes.Count();
    TBool attributeFound = EFalse;
    while ((index--) && (!attributeFound))
        {
        if (aAttributes[index].Attribute().LocalName().DesC() == aName)
            {
            attributeFound = ETrue;
            aValue.Set(aAttributes[index].Value().DesC());
            }
        }
    
    TInt err = KErrNone;
    
    if (!attributeFound)
        err = KErrNotFound;
    
    return err;
    }

// Finds an attribute of the given name and gets its value (coverting the string hex value to a UInt)
// Returns KErrNone if the attribute is present in the list, KErrNotFound otherwise
// Returns KErrCorrupt if the string is not a valid hex number
TInt COomConfigParser::GetValueFromHexAttributeList(const RAttributeArray& aAttributes, const TDesC8& aName, TUint& aValue)
    {
    TPtrC8 hexString;
    TInt err = GetValueFromAttributeList(aAttributes, aName, hexString);

    if (hexString == KOomConfigDefaultAppUid)
        {
        // This is a special case
        // When we hit this value in a hex field then we return the default app UID
        aValue = KOomDefaultAppId;
        }
    else if (hexString == KOomConfigDefaultPluginUid)
        {
        // This is a special case
        // When we hit this value in a hex field then we return the default app UID
        aValue = KOomDefaultPluginId;
        }
    else if (hexString == KOomConfigBusyAppUid)
        {
        aValue = KOomBusyAppId;
        }
    else if (hexString == KOomConfigHighPriorityAppUid)
        {
        aValue = KOomHighPriorityAppId;
        }
    else if (err == KErrNone)
        {
        TLex8 hexLex(hexString);
        err = hexLex.Val(aValue, EHex);
        if (err != KErrNone)
            err = KErrCorrupt;
        }
    
    return err;
    }

// Finds an attribute of the given name and gets its value (coverting the string decimal value to a UInt)
// Returns KErrNone if the attribute is present in the list, KErrNotFound otherwise
// Returns KErrCorrupt if the string is not a valid decimal number
TInt COomConfigParser::GetValueFromDecimalAttributeList(const RAttributeArray& aAttributes, const TDesC8& aName, TUint& aValue)
    {
    TPtrC8 decimalString;
    TInt err = GetValueFromAttributeList(aAttributes, aName, decimalString);

    if (err == KErrNone)
        {
        if (decimalString == KOomAttibuteNeverClose)
            aValue = KOomPriorityInfinate;
        else
            {
            TLex8 decimalLex(decimalString);
            err = decimalLex.Val(aValue, EDecimal);
            if (err != KErrNone)
                err = KErrCorrupt;
            }
        }
    
    return err;
    }

TInt COomConfigParser::GetValueFromDecimalAttributeList(const RAttributeArray& aAttributes, const TDesC8& aName, TInt& aValue)
    {
    TUint uintValue;
    TInt err = GetValueFromDecimalAttributeList(aAttributes, aName, uintValue);
    aValue = uintValue;
    return err;
    }

TInt COomConfigParser::GetValueFromBooleanAttributeList(const RAttributeArray& aAttributes, const TDesC8& aName, TBool& aValue)
    {
    TPtrC8 ptrValue;
    TInt err = GetValueFromAttributeList(aAttributes, aName, ptrValue);
    if (err == KErrNone)
        {
        if (ptrValue == KOomAttributeTrue || ptrValue == KOomAttribute1)
            {
            aValue = ETrue;
            }
        else if (ptrValue == KOomAttributeFalse || ptrValue == KOomAttribute0)
            {
            aValue = EFalse;
            }
        else
            {
            err = KErrCorrupt;
            }
        }
    return err;
    }

void COomConfigParser::SetPluginSyncMode(const RAttributeArray& aAttributes, COomRunPluginConfig& aRunPluginConfig)
    {
    TPtrC8 syncModeString;
    TInt err = GetValueFromAttributeList(aAttributes, KOomAttibuteSyncMode, syncModeString);
    
    if (err == KErrNone)
        // If there is no specified sync mode then leave it as the default
        {
        TOomSyncMode syncMode = EContinue;
        
        if (syncModeString == KOomConfigSyncModeContinue)
            syncMode = EContinueIgnoreMaxBatchSize;
        else if (syncModeString == KOomConfigSyncModeCheck)
            syncMode = ECheckRam;
        else if (syncModeString == KOomConfigSyncModeEstimate)
            syncMode = EEstimate;
        else
            ConfigError(KOomErrInvalidSyncMode);
        
        if (err == KErrNone)
            {
            aRunPluginConfig.iSyncMode = syncMode;
            }
        }
    }

// Check that the current state is as expected
// If not then the specified config error is generated
void COomConfigParser::CheckState(TOomParsingState aExpectedState, TInt aError)
    {
    if (iState != aExpectedState)
        ConfigError(aError);
    }

// Check that the current state is as expected
// If not then the specified config error is generated
// This version checks to ensure that the current state matches either of the passed in states
void COomConfigParser::CheckState(TOomParsingState aExpectedState1, TOomParsingState aExpectedState2, TInt aError)
    {
    if ((iState != aExpectedState1)
            && (iState != aExpectedState2))
        ConfigError(aError);
    }

void COomConfigParser::ChangeState(TOomParsingState aState)
    {
    iState = aState;
    }