tracesrv/tracecore/btrace_handler/src/BTraceOstCategoryBitmap.cpp
changeset 56 aa2539c91954
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/src/BTraceOstCategoryBitmap.cpp	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,1446 @@
+// Copyright (c) 2007-2010 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:
+// Trace Core 
+//
+
+#include <e32def.h>
+#include <e32btrace.h>
+
+#include "BTraceOstCategoryBitmap.h"
+#include "TraceCoreOstHeader.h"
+#include "TraceCoreCommon.h"
+#include "TraceCore.h"
+#include "TraceCoreNotifier.h"
+#include "TraceCoreConstants.h"
+#include "TraceCoreDebug.h"
+#include "TraceCoreSettings.h"
+#include "BTraceOstCategoryHandler.h"
+
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "BTraceOstCategoryBitmapTraces.h"
+#endif
+
+
+//Split: These needed from sos_mon_isi_m.h (which is removed):
+#define SOS_MON_TRACECORE_OST_ACTIVATION_REQ 0xD4
+
+// OST message type
+#define SOS_MON_TRACECORE_OST_ACTIVATION 1
+#define SOS_MON_TRACECORE_OST_ACTIVATION_QUERY 2
+
+/**
+ * OST activation message types
+ */
+#define SOS_MON_TRACECORE_OST_DEACTIVATE 0
+#define SOS_MON_TRACECORE_OST_ACTIVATE 1
+#define SOS_MON_TRACECORE_OST_DEACTIVATE_ALL 2
+#define SOS_MON_TRACECORE_OST_ACTIVATE_ALL 3
+#define SOS_MON_TRACECORE_OST_OVERWRITE 4
+
+
+/**
+ * Offset to OST message id
+ * Field length 1 byte
+ */
+const TInt KOstMessageIdOffset = 0;
+
+/**
+ * Offset to activation info
+ * Field length 1 byte
+ */
+const TInt KOstActivationInfoOffset = 3;
+
+/**
+ * Offset to Number of groups field
+ * Field length 4 bytes
+ */
+const TInt KOstNumberOfGroupsOffset = 4;
+
+/**
+ * Offset to Component id
+ * Field length 4 bytes
+ */
+const TInt KOstComponentIdOffset = 8;
+
+/**
+ * Offset to 1st Group Id
+ * Field length 2 bytes
+ */
+const TInt KOstGroupIdOffset = 12;
+
+/**
+ * Minimum OST frame length
+ *  - Message ID            (1 byte)
+ *  - Fillers               (2 bytes)
+ *  - Activation info       (1 byte)
+ *  - Number of groups      (4 bytes)
+ *  - Component ID          (4 bytes)
+ */
+const TInt KOstMinFrameLength = 12;
+
+/**
+ * Group id length, 16bits, 2 bytes
+ */
+const TUint KGroupIdLength = 2;
+
+/**
+ * Increase array size
+ */
+const TUint KOstComponentsArrayGranularity = 8;
+
+/**
+ * Maximum activation buffer length
+ */
+const TUint32 KMaxActivationBufferLength = 1024 * 16;
+
+/**
+ * Constants for bit manipulation
+ */
+const TInt K8BitShift = 8;
+const TInt K16BitShift = 16;
+const TInt K24BitShift = 24;
+const TInt K8BitMask = 0xff;
+const TInt K4Bytes = 4;
+const TInt K2Bytes = 2;
+
+/**
+ * Number of bytes to shift the group ID
+ */
+#define GRP_SHIFT 16
+
+/**
+ * Number of bytes to shift the group ID
+ */
+#define GRP_MASK 0x00ff0000
+
+/**
+ * Dummy handler used when no traces activated
+ */
+TBool DummyBTraceHandler(TUint32,TUint32,const TUint32,const TUint32,const TUint32,const TUint32,const TUint32,const TUint32)
+	{
+	return EFalse;
+	}
+
+BTrace::THandler oldHandler;
+
+/**
+ * Reads 16 bits from buffer
+ */
+TUint32 Read16(const TUint8* aPtr)
+    {
+    return ( (TUint32 )*aPtr ) | ( ( (TUint32 )*(aPtr + 1 ) ) << K8BitShift ); // CodForChk_Dis_Magic
+    }
+
+/**
+ * Reads 32 bits from buffer
+ */
+TUint32 Read32(const TUint8* aPtr)
+    {
+    return ( (TUint32 )*aPtr ) |
+           ( ( (TUint32 )*(aPtr + 1 ) ) << K8BitShift ) | // CodForChk_Dis_Magic
+           ( ( (TUint32 )*(aPtr + 2 ) ) << K16BitShift ) | // CodForChk_Dis_Magic
+           ( ( (TUint32 )*(aPtr + 3 ) ) << K24BitShift ); // CodForChk_Dis_Magic
+    }
+
+/**
+ * Endian swapper for 32-bit variable
+ */
+#define SWAP32( num ) ( \
+    ( ( ( num ) & 0xff000000 ) >> K24BitShift ) | ( ( ( num ) & 0x00ff0000 ) >> K8BitShift  ) | \
+    ( ( ( num ) & 0x0000ff00 ) <<  K8BitShift ) | ( ( ( num ) & 0x000000ff ) << K24BitShift ) )
+
+/**
+ * Endian swapper for 16-bit variable
+ */
+#define SWAP16( num ) ( ( ( ( num ) & 0xff00 ) >> K8BitShift ) | ( ( ( num ) & 0x00ff ) << K8BitShift  ) )
+
+/**
+ * Constructor
+ */
+DBTraceOstCategoryBitmap::DBTraceOstCategoryBitmap(DBTraceOstCategoryHandler* aBTraceOstCategoryHandler) :
+      iOstComponents(NULL),
+      iTmpArray(NULL),
+      iChangedArray(NULL),
+      iActivationBuffer(NULL),
+      iBTraceOstCategoryHandler( aBTraceOstCategoryHandler )
+    {
+    }
+
+/**
+ * Destructor
+ */
+DBTraceOstCategoryBitmap::~DBTraceOstCategoryBitmap()
+    {
+    Kern::Free( iActivationBuffer );
+    iActivationBuffer = NULL;
+    
+    CleanupComponentsArrays();
+    }
+
+/**
+ * Init TraceBitmap
+ */
+TInt DBTraceOstCategoryBitmap::Init()
+    {
+    iOstComponents = new RArray<TOstComponent>(KOstComponentsArrayGranularity);
+    if(!iOstComponents)
+        return KErrNoMemory;
+    iTmpArray = new RArray<TOstComponent>(KOstComponentsArrayGranularity);
+    if(!iTmpArray)
+        {
+        CleanupComponentsArrays();
+        return KErrNoMemory;
+        }
+    iChangedArray = new RArray<TOstComponent>(1);
+    if(!iChangedArray)
+        {
+        CleanupComponentsArrays();
+        return KErrNoMemory;
+        }
+    
+    AllocateActivationBuffer();
+        
+    // Init bitmap
+    TInt err = DTraceCoreActivationBase::Init( SOS_MON_TRACECORE_OST_ACTIVATION_REQ);
+    if (err == KErrNone)
+        {
+        // Subscribe message
+        err = DTraceCoreActivationBase::SubscribeMessage(OstConstants::OstBaseProtocol::KOstTraceActivationProtocol,
+                EMessageHeaderFormatOst);
+
+        // Save old BTrace handler and use dummy for better performance
+        oldHandler = BTrace::SetHandler(DummyBTraceHandler);
+        }
+    
+    return err;
+    }
+
+/**
+ * Activate trace group
+ *
+ * @param aComponentId The component ID
+ * @param aGroupId The group ID
+ */
+void DBTraceOstCategoryBitmap::ActivateTrace(const TUint32 aComponentId, const TUint32 aGroupId)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_ACTIVATETRACE_ENTRY,"> DBTraceOstCategoryBitmap::ActivateTrace CID:0x%x GID:0x%x", aComponentId, aGroupId );
+    //TODO: check is thread context (assert)
+    //TODO: can be executed only from iActivationQ (__ASSERT_DEBUG)
+    
+    if (GroupIdIsValid(aGroupId))
+      {
+    //TODO: check how many users use this array (use atomics to increment/decrement)
+      CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+      CleanupComponentsArray(*iChangedArray);
+      
+      TInt index = AddComponentId(aComponentId, *iTmpArray);
+      AddGroupId(aComponentId, aGroupId, index, *iTmpArray, *iChangedArray);
+      SetNewComponentsArrayPtr( iTmpArray );
+      
+      //notify internal listeners and update internal activation cache
+      HandleTraceActivationChanges(*iChangedArray);
+      NotifyInternalActivation( EFalse, aComponentId );
+      }
+    else
+      {
+      OstTrace0( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_ACTIVATETRACE_INVALID_GROUP,"DBTraceOstCategoryBitmap::ActivateTrace - Invalid group ID");
+      // Notifies activation interfaces of invalid group ID
+      DTraceCore* traceCore = DTraceCore::GetInstance();
+      if ( traceCore != NULL )
+          {
+          traceCore->GetNotifier().TraceError( aComponentId, aGroupId, KErrArgument );
+          }
+      }
+    }
+
+/**
+ * Deactivate trace group
+ *
+ * @param aComponentId The component ID
+ * @param aGroupId The group ID
+ */
+void DBTraceOstCategoryBitmap::DeactivateTrace(const TUint32 aComponentId, const TUint32 aGroupId)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_DEACTIVATETRACE_ENTRY,"> DBTraceOstCategoryBitmap::DeactivateTrace. CID:0x%x GID:0x%x", aComponentId, aGroupId );
+    if (ComponentIdIsValid(aComponentId) )
+        {
+        if (GroupIdIsValid(aGroupId))
+            {
+            
+            TInt componentIndex = FindComponentId(aComponentId, *iOstComponents);
+            if (componentIndex >= 0)
+                {
+                CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+                CleanupComponentsArray(*iChangedArray);
+                RemoveGroupId(aComponentId, aGroupId, componentIndex, *iTmpArray, *iChangedArray);
+                if ((*iTmpArray)[ componentIndex ].iGroups.Count() == 0)
+                    {
+                    RemoveComponentId(aComponentId, EFalse, *iTmpArray, *iChangedArray);
+                    }
+                
+                //Swap pointers.
+                SetNewComponentsArrayPtr( iTmpArray );
+             
+                //notify internal listeners and update internal activation cache
+                HandleTraceActivationChanges(*iChangedArray);
+                NotifyInternalActivation( EFalse, aComponentId );
+                }
+            }
+        else
+            {
+            OstTrace0( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_DEACTIVATETRACE_INVALID_GROUP,"DBTraceOstCategoryBitmap::DeactivateTrace - Invalid group ID");
+            // Notifies activation interfaces of invalid group ID
+            DTraceCore* traceCore = DTraceCore::GetInstance();
+            if ( traceCore != NULL )
+                {
+                traceCore->GetNotifier().TraceError( aComponentId, aGroupId, KErrArgument );
+                }
+            }
+        }
+    }
+
+/**
+ * Deactivates all groups from a component
+ * 
+ * @param aComponentId The component ID
+ */
+void DBTraceOstCategoryBitmap::DeactivateAll(const TUint32 aComponentId)
+    {
+    OstTrace1( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_DEACTIVATEALL_ENTRY,"> DBTraceOstCategoryBitmap::DeactivateAll. CID:0x%x", aComponentId );
+
+    CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+    CleanupComponentsArray(*iChangedArray);
+    
+    if( RemoveComponentId(aComponentId, ETrue, *iTmpArray, *iChangedArray) != KErrNotFound)
+        SetNewComponentsArrayPtr( iTmpArray );
+    
+    //notify internal listeners and update internal activation cache
+    HandleTraceActivationChanges(*iChangedArray);
+    NotifyInternalActivation( EFalse, aComponentId );
+    }
+
+/**
+ * Reads the bitmap from the settings. If the settings does 
+ * not have a bitmap, the current bitmap is written to it
+ * 
+ * @param aSettings the settings
+ */
+void DBTraceOstCategoryBitmap::ReadFromSettings(DTraceCoreSettings& aSettings)
+    {
+    // Read buffer
+    if ( aSettings.Read( iActivationBuffer, KMaxActivationBufferLength ) )
+    	{
+        CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+        CleanupComponentsArray(*iChangedArray);
+        
+	    TUint8* ptr = iActivationBuffer;
+	    TInt componentcount = Read32FromBuffer(ptr);
+	    TC_TRACE( ETraceLevelFlow, Kern::Printf( " DBTraceOstCategoryBitmap::ReadFromSettings() components=%d", componentcount ) );
+	    TInt groupcount = 0;
+	    TUint32 componentID = 0;
+	    TUint16 groupID = 0;
+	    TInt index = 0;
+	    for ( TInt i = 0; i < componentcount; ++i )
+	    	{
+	    	// Read number of group IDs (4 bytes)
+	    	groupcount = Read32FromBuffer(ptr);
+	    	// Read component ID (4 bytes)
+	    	componentID = Read32FromBuffer(ptr);
+	    	index = AddComponentId(componentID, *iTmpArray);
+	    	// Read group IDs (2 bytes each)
+	    	for ( TInt k = 0; k < groupcount; ++k )
+	    		{
+	    		groupID = Read16FromBuffer(ptr);
+	            if (GroupIdIsValid(groupID))
+	                {
+	                AddGroupId(componentID, groupID, index, *iTmpArray, *iChangedArray);
+	                }
+	            else
+	                {
+	                // Notifies activation interfaces of invalid group ID
+	                DTraceCore* traceCore = DTraceCore::GetInstance();
+	                if ( traceCore != NULL )
+	                    {
+	                    traceCore->GetNotifier().TraceError( componentID, groupID, KErrArgument );
+	                    }
+	                }            
+	    		}
+	    	}
+	    
+	    //swap pointers and clean up
+	    SetNewComponentsArrayPtr( iTmpArray );
+	    HandleTraceActivationChanges(*iChangedArray);
+	    NotifyInternalActivation( ETrue, componentID );
+    	}
+    }
+
+/**
+ * Writes the bitmap to given settings
+ * 
+ * @param aSettings the settings where bitmap is written
+ */
+void DBTraceOstCategoryBitmap::WriteToSettings(DTraceCoreSettings& aSettings)
+    { 
+    TUint8* ptr = iActivationBuffer;
+    TInt componentcount = iOstComponents->Count();
+    WriteToBuffer(ptr, (TUint32)(componentcount));
+    for ( TInt i = 0; i < componentcount; ++i )
+        {
+        // Add number of group IDs (4 bytes)
+        TInt groupcount = (*iOstComponents)[i].iGroups.Count();
+        WriteToBuffer(ptr, (TUint32)(groupcount));
+        // Add component ID (4 bytes)
+        WriteToBuffer(ptr, (*iOstComponents)[i].iComponentId);
+        TC_TRACE( ETraceLevelFlow, Kern::Printf( " DBTraceOstCategoryBitmap::WriteToSettings() component=0x%x with %d groups",(*iOstComponents)[i].iComponentId, groupcount ) );
+        // Add group IDs (2 bytes each)
+        for ( TInt k = 0; k < groupcount; ++k )
+            {
+            WriteToBuffer(ptr, (TUint16)((*iOstComponents)[i].iGroups[k]) );
+            }
+        }
+    // Save buffer
+    aSettings.Write( iActivationBuffer, KMaxActivationBufferLength );
+    }
+
+/**
+ * Checks if trace points with a specific component ID and group ID are
+ * currently active
+ *
+ * @param aComponentId The component ID
+ * @param aTraceWord The trace word containing the group ID to check
+ * @return ETrue if trace is active, EFalse if not
+ */
+TBool DBTraceOstCategoryBitmap::IsTraceActivated(const TUint32 aComponentId, TUint32 aTraceWord)
+    {
+    // Find component
+    TOstComponent ostComponent;
+    ostComponent.iComponentId = aComponentId;
+    TInt irq = ReadLock();
+    TInt index = iOstComponents->FindInUnsignedKeyOrder(ostComponent);
+    if (index != KErrNotFound)
+        {
+        index = (*iOstComponents)[ index ].iGroups.FindInOrder((aTraceWord & GRP_MASK) >> GRP_SHIFT);
+        }
+    TBool ret = (index != KErrNotFound );
+    ReadUnlock(irq);
+    return ret;
+    }
+
+/**
+ * Find component id index in array
+ * 
+ * @param aComponentId Component id to be searched
+ * @param aOstComponents Array to search through
+ * @return index of component id in array if found, otherwise KErrNotFound
+ */
+TInt DBTraceOstCategoryBitmap::FindComponentId(TUint32 aComponentId, RArray<TOstComponent>& aOstComponents)
+    {
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_FINDCOMPONENTID_ENTRY,"> DBTraceOstCategoryBitmap::FindComponentId 0x%x", aComponentId );
+    TOstComponent tempComponent;
+    tempComponent.iComponentId = aComponentId;
+    // Check index of component id in array
+    TInt index = aOstComponents.FindInUnsignedKeyOrder(tempComponent);
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_FINDCOMPONENTID_EXIT,"< DBTraceOstCategoryBitmap::FindComponentId. Index:%d", index );
+    return index;
+    }
+
+/**
+ * Add component id to array
+ * 
+ * @param aComponentId Component id to be added
+ * @return index of (added of existing) component id in array or an error code
+ */
+TInt DBTraceOstCategoryBitmap::AddComponentId(TUint32 aComponentId, RArray<TOstComponent>& aOstComponents)
+    {
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_ADDCOMPONENTID_ENTRY,"> DBTraceOstCategoryBitmap::AddComponentId 0x%x", aComponentId );
+    TOstComponent tempComponent;
+    tempComponent.iComponentId = aComponentId;
+    TInt index(KErrNotFound);
+    // Add component id
+    TInt err = aOstComponents.InsertInUnsignedKeyOrder(tempComponent);
+    OstTraceExt2( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_ADDCOMPONENTID_INSERT_FAILED,"DBTraceOstCategoryBitmap::AddComponentId - Insert returned. CID:0x%x Err:%d",(TUint)aComponentId, (TInt)err );
+    if ( (err == KErrNone ) || (err == KErrAlreadyExists ))
+        {
+        // Check index of component id in array
+        index = aOstComponents.FindInUnsignedKeyOrder(tempComponent);
+        }
+        
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_ADDCOMPONENTID_EXIT,"< DBTraceOstCategoryBitmap::AddComponentId. Index:%d", index );
+    return index;
+    }
+
+/**
+ * Remove component id in array.
+ * 
+ * @param aComponentId Component id to be removed
+ * @param aNotifyActivationListeners if true, inform activation notification listeners
+ * @param aOstComponents array from which component has to be removed 
+ * @param aChangedArray Array that will be updated to contain the changed TOstComponent objects
+ * @return index of removed component id if found, otherwise KErrNotFound
+ */
+TInt DBTraceOstCategoryBitmap::RemoveComponentId(TUint32 aComponentId, TBool aNotifyActivationListeners, 
+        RArray<TOstComponent>& aOstComponents, RArray< TOstComponent >& aChangedArray )
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_REMOVECOMPONENTID_ENTRY, "> DBTraceOstCategoryBitmap::RemoveComponentId 0x%x %d", aComponentId, aNotifyActivationListeners );
+    
+    // Check index of component id in array
+    TInt index = FindComponentId(aComponentId, aOstComponents);
+    if (index >= 0)
+        {
+        // Component id found - Remove it
+        aOstComponents.Remove(index);
+        
+        // Inform about removal if aNotifyActivationListeners is true
+        if ( aNotifyActivationListeners )
+        	{
+            AddGroupToChangedArray(aChangedArray, aComponentId, KAllGroups);
+        	}
+        }
+	
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_REMOVECOMPONENTID_EXIT,"< DBTraceOstCategoryBitmap::RemoveComponentId. Index:%d", index );
+    return index;
+    }
+
+/**
+ * Adds group id to array
+ * 
+ * @param aComponentId Component where the group belongs
+ * @param aGroupId Group id to be added
+ * @param aIndex Index of component array where to add the groupId
+ * @param aOstComponents Array with TOstComponent objects.
+ * @param aChangedArray Array that will be updated to contain the changed TOstComponent objects
+ */
+TInt DBTraceOstCategoryBitmap::AddGroupId(TUint32 aComponentId, TGroupId aGroupId, TInt aIndex, 
+        RArray<TOstComponent>& aOstComponents, RArray<TOstComponent>& aChangedArray)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_ADDGROUPID_ENTRY,"> DBTraceOstCategoryBitmap::AddGroupId. GID:0x%x. Index:%d", (TUint32) aGroupId, (TUint32) aIndex );
+    TInt ret = KErrNone;
+
+    if (aIndex >= 0 && aIndex < aOstComponents.Count() )
+        {
+        // Add group Id
+        ret = aOstComponents[ aIndex ].iGroups.InsertInOrder(aGroupId);
+        if (ret == KErrNone)
+            {
+            // Inform notifier that trace has been activated
+            DTraceCore* traceCore = DTraceCore::GetInstance();
+            if (traceCore != NULL)
+                {
+                // Don't activate Kernel groups from BTrace here, it will be done in KernelHandler
+                if ((TUint) aGroupId > KMaxKernelCategory)
+                    {
+                    BTrace::SetFilter((TUint) aGroupId, 1);
+                    }
+                
+                // Add group to changed array
+                AddGroupToChangedArray(aChangedArray, aComponentId, aGroupId);
+                }
+            else
+                {
+                ret = KErrGeneral;
+                }
+            }
+        else
+            if (ret == KErrAlreadyExists)
+                {
+                ret = KErrNone;
+                }
+        }
+    else
+        {
+        ret = KErrArgument;
+        }
+    
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_ADDGROUPID_EXIT,"< DBTraceOstCategoryBitmap::AddGroupId. Ret:%d", ret );
+    return ret;
+    }
+
+/**
+ * Removes group id from array
+ * 
+ * @param aComponentId Component where the group belongs
+ * @param aGroupId Group id to be removed
+ * @param aIndex Index of component array from where to remove the groupId
+ * @param aOstComponents Array with TOstComponent objects.
+ * @param aChangedArray Array that will be updated to contain the changed TOstComponent objects
+ */
+TInt DBTraceOstCategoryBitmap::RemoveGroupId(TUint32 aComponentId, TGroupId aGroupId, TInt aIndex, 
+        RArray<TOstComponent>& aOstComponents, RArray< TOstComponent >& aChangedArray)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_REMOVEGROUPID_ENTRY,"> DBTraceOstCategoryBitmap::RemoveGroupId. GID:0x%x. Idx:%d", (TUint32) aGroupId, (TUint32) aIndex );
+    TInt ret = KErrNone;
+    if (aIndex >= 0 && aIndex < aOstComponents.Count() )
+        {
+        // Component id found, remove group ID
+        TInt groupIndex = aOstComponents[ aIndex ].iGroups.FindInOrder(aGroupId);
+        if (groupIndex >= 0)
+            {
+            aOstComponents[ aIndex ].iGroups.Remove(groupIndex);
+            // Inform notifier that trace has been deactivated
+            DTraceCore* traceCore = DTraceCore::GetInstance();
+            if (traceCore != NULL)
+                {
+                BTrace::SetFilter((TUint) aGroupId, 0);                        
+                OstTrace1( TRACE_INTERNAL, DBTRACEOSTCATEGORYBITMAP_REMOVEGROUPID_NOTIFIER_DEACTIVATED,"DBTraceOstCategoryBitmap::RemoveGroupId - Group deactivated, calling notifier. GID:0x%x",(TUint32) aGroupId );
+                
+                AddGroupToChangedArray(aChangedArray, aComponentId, aGroupId);                
+                ret = KErrNone;
+                }
+            else
+                {
+                ret = KErrGeneral;
+                }
+            }
+        else
+            {
+            ret = KErrNone;
+            }
+        }
+    else
+        {
+        ret = KErrArgument;
+        }
+
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_REMOVEGROUPID_EXIT,"< DBTraceOstCategoryBitmap::RemoveGroupId. Ret:%d", ret );
+    return ret;
+    }
+
+/**
+ * Read OST Protocol frame from OST protocol message.
+ * 
+ * @pre On entry to this methods writer mutex (iActivationWriteLock) must be held.
+ * 
+ * @param aMessage Received message
+ * @param aFrameStartIndex Start offset of the frame in message
+ * @return Offset after read frame
+ */
+TInt DBTraceOstCategoryBitmap::ReadOstProtocolFrame(const TDesC8& aMessage, TUint32 aFrameStartIndex)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTPROTOCOLFRAME_ENTRY, "< DBTraceOstCategoryBitmap::ReadOstProtocolFrame. aMessage:%s, aFrameStartIndex:%u", aMessage,aFrameStartIndex );
+    
+    //__ASSERT_MUTEX(iActivationWriteLock);
+    TInt retPosition = 0;
+    TInt length = aMessage.Length();
+
+    TInt ostBaseHeaderSize = OstHeader::OstBaseProtocol::KOstBaseHeaderSize;
+    TInt applicationIdOffset = OstHeader::OstTraceActivation::SetApplicationStatusRequest::KApplicationIdOffset-ostBaseHeaderSize;
+    TInt activationStatusOffset = 
+                      OstHeader::OstTraceActivation::SetApplicationStatusRequest::KActivationStatusOffset-ostBaseHeaderSize;
+    
+    TInt groupIdOffset = OstHeader::OstTraceActivation::SetApplicationStatusRequest::KGroupIdOffset-ostBaseHeaderSize;
+    TInt activated = OstConstants::OstTraceActivation::ActivationStatus::KApplicationTracesActivated;
+    TInt deactivated = OstConstants::OstTraceActivation::ActivationStatus::KApplicationTracesDeactivated;
+
+    // Checks that buffer is large enough for the frame
+    if (length >= (activationStatusOffset +1 /*1==activatin status  size*/- ostBaseHeaderSize ))
+        {
+        const TUint8* frameStart = aMessage.Ptr() + aFrameStartIndex;
+        // Check if activation or deactivation
+        TUint8 activationStatus = *(frameStart + activationStatusOffset );
+
+        if ( (activationStatus == activated ) || (activationStatus == deactivated ))
+            {
+            // One frame may contain multiple group ID's. Each occupy 2 bytes
+            TUint32 numberOfGroups = (length-groupIdOffset)/2; // CodForChk_Dis_Magic
+
+            if ((length-groupIdOffset)%2!=0) // CodForChk_Dis_Magic
+                {
+                numberOfGroups--;
+                }
+            // One frame contains one component id
+            TUint32 applicationId = Read32(frameStart + applicationIdOffset);
+
+            // Swap byte order
+            applicationId = SWAP32( applicationId );
+            
+            CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+            CleanupComponentsArray(*iChangedArray);
+            
+            TInt index(0); 
+            if (activationStatus == activated)
+                {
+                index = AddComponentId(applicationId, *iTmpArray);
+                }
+            else
+                {
+                index = FindComponentId(applicationId, *iTmpArray);
+                }
+
+            if (index >= 0)
+                {
+                // Updates the group ID's that have changed
+                retPosition = ReadOstProtocolFrameGroups(aMessage, aFrameStartIndex, activationStatus, index, applicationId, *iTmpArray, *iChangedArray);
+                aFrameStartIndex = retPosition;
+                }
+            else
+                {
+                OstTrace1( TRACE_INTERNAL, DBTRACEOSTCATEGORYBITMAP_READOSTFRAME_NOT_FOUND,"DBTraceOstCategoryBitmap::ReadOstFrame - Component ID not found: 0x%x", applicationId );
+                }
+            
+            //swap pointers and cleanup
+            SetNewComponentsArrayPtr(iTmpArray);
+           
+            //notify internal listeners and update internal activation cache
+            HandleTraceActivationChanges(*iChangedArray);
+            NotifyInternalActivation( EFalse, applicationId );
+            
+            }
+        }
+
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTFRAME_EXIT, "< DBTraceOstCategoryBitmap::ReadOstFrame. Ret:%d", retPosition );
+    return retPosition;
+    }
+
+/**
+ * Read the groups from an OST frame
+ * 
+ * @param aMessage Received message
+ * @param aFrameStartIndex Start offset of the frame in message
+ * @param aActivationInfo Activation / deactivation flag
+ * @param aComponentIndex The index of the component where the groups belong to
+ * @param aComponentId The component ID
+ * @param aOstComponents Array with TOstComponent objects.
+ * @param aChangedArray Array that will be updated to contain the changed TOstComponent objects
+ * @return Offset after read frame
+ */
+TInt DBTraceOstCategoryBitmap::ReadOstProtocolFrameGroups(const TDesC8& aMessage, TInt aFrameStartIndex, TUint8 aActivationInfo,
+        TInt aComponentIndex, TUint32 aComponentId, RArray<TOstComponent>& aOstComponents, RArray< TOstComponent >& aChangedArray)
+    {
+    OstTraceExt3( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTPROTOCOLFRAMEGROUPS_ENTRY,"< DBTraceOstCategoryBitmap::ReadOstProtocolFrameGroups. aMessage:%s, aFrameStartIndex:%u, aActivationInfo:%u", aMessage,aFrameStartIndex, aActivationInfo );
+   
+    TInt length(aMessage.Length() );
+    TInt ostBaseHeaderSize = OstHeader::OstBaseProtocol::KOstBaseHeaderSize;
+    TInt groupIdOffset = OstHeader::OstTraceActivation::SetApplicationStatusRequest::KGroupIdOffset-ostBaseHeaderSize;
+    TInt activated = OstConstants::OstTraceActivation::ActivationStatus::KApplicationTracesActivated;
+    TInt deactivated = OstConstants::OstTraceActivation::ActivationStatus::KApplicationTracesDeactivated;
+
+    const TUint8* frameStart = aMessage.Ptr() + aFrameStartIndex;
+    
+    TInt offset = groupIdOffset;
+    TInt retPosition( 0);
+    
+    // One frame may contain multiple group ID's. Each occupy 2 bytes
+    TUint32 numberOfGroups = (length-groupIdOffset) / 2; // CodForChk_Dis_Magic
+    
+    if ((length-groupIdOffset) % 2 != 0) // CodForChk_Dis_Magic
+        {
+        numberOfGroups--;
+        }
+
+    TBool swapGroups = ETrue;
+    // This is supporting both byte orders
+    if (numberOfGroups > KMaxGroupId)
+        {
+        swapGroups = ETrue;
+        numberOfGroups = SWAP32( numberOfGroups );
+        }
+    
+    // Read Group ids and remove from array
+    for (TUint i = 0; i < numberOfGroups; i++)
+        {
+        TUint16 groupId = Read16(frameStart + offset);
+        if (swapGroups)
+            {
+            groupId = SWAP16( groupId );
+            }
+        offset += KGroupIdLength;
+        if (GroupIdIsValid(groupId)) 
+        	{
+			if (aActivationInfo == activated)
+				{
+				AddGroupId(aComponentId, groupId, aComponentIndex, aOstComponents, aChangedArray);
+				}
+			else
+				{
+				RemoveGroupId(aComponentId, groupId, aComponentIndex, aOstComponents, aChangedArray);
+				}
+        	}
+        else
+            {
+            // Notifies activation interfaces of invalid group ID
+            DTraceCore* traceCore = DTraceCore::GetInstance();
+            if ( traceCore != NULL )
+                {
+                traceCore->GetNotifier().TraceError( aComponentId, groupId, KErrArgument );
+                }
+            }
+        }
+    // If all groups were removed from the component, it can also be removed
+    if ( (aActivationInfo == deactivated ) && (aOstComponents[ aComponentIndex ].iGroups.Count() == 0 ))
+        {
+        RemoveComponentId(aComponentId, EFalse, aOstComponents, aChangedArray);
+        }
+    // The next frame offset is returned
+    retPosition = aFrameStartIndex + offset;
+        
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTPROTOCOLFRAMEGROUPS_EXIT,"< DBTraceOstCategoryBitmap::ReadOstFrameGroups. Ret:%d", retPosition );
+    return retPosition;
+    }
+
+/**
+ * Read OST frame from ISI message.
+ * 
+ * @pre On entry to this methods writer mutex (iActivationWriteLock) must be held.
+ * 
+ * @param aMessage Received message
+ * @param aFrameStartIndex Start offset of the frame in message
+ * @return Offset after read frame
+ */
+TInt DBTraceOstCategoryBitmap::ReadOstFrame(const TDesC8& aMessage, TUint32 aFrameStartIndex)
+    {
+    TInt retPosition = 0;
+    TUint length = aMessage.Length();
+    // Checks that buffer is large enough for the frame
+    if (length >= (aFrameStartIndex + KOstMinFrameLength ))
+        {
+        const TUint8* frameStart = aMessage.Ptr() + aFrameStartIndex;
+        // Check if activation or deactivation
+        TUint8 activationInfo = *(frameStart + KOstActivationInfoOffset );
+        
+        if ( (activationInfo == SOS_MON_TRACECORE_OST_DEACTIVATE ) || (activationInfo == SOS_MON_TRACECORE_OST_ACTIVATE )
+                || (activationInfo == SOS_MON_TRACECORE_OST_OVERWRITE ))
+            {
+            // One frame may contain multiple group ID's. Each occupy 2 bytes
+            (void) Read32(frameStart + KOstNumberOfGroupsOffset); // This is the numberOfGroups
+            // One frame contains one component id
+            TUint32 componentId = Read32(frameStart + KOstComponentIdOffset);
+            // Component Id in message is in Big Endian format so it need to be swap to Little Endian format
+            componentId = SWAP32( componentId );
+
+            CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+            CleanupComponentsArray(*iChangedArray);
+            
+            TInt index( 0);
+            if ( (activationInfo == SOS_MON_TRACECORE_OST_ACTIVATE ) || (activationInfo == SOS_MON_TRACECORE_OST_OVERWRITE ))
+                {
+                index = AddComponentId(componentId, *iTmpArray);
+                }
+            else
+                {
+                index = FindComponentId(componentId, *iTmpArray);
+                }
+            if (index >= 0)
+                {
+                // Updates the group ID's that have changed
+                retPosition = ReadOstFrameGroups(aMessage, aFrameStartIndex, activationInfo, index, componentId, *iTmpArray, *iChangedArray);
+                }
+            
+            //swap pointers and cleanup
+            SetNewComponentsArrayPtr(iTmpArray);
+            
+            //notify internal listeners and update internal activation cache
+            HandleTraceActivationChanges(*iChangedArray);
+            NotifyInternalActivation( EFalse, componentId );
+            }
+        else
+            if (activationInfo == SOS_MON_TRACECORE_OST_DEACTIVATE_ALL)
+                {
+                // Deactivate all groups from component
+                TUint32 componentId = Read32(frameStart + KOstComponentIdOffset);
+                // Component Id in message is in Big Endian format so it need to be swap to Little Endian format
+                componentId = SWAP32( componentId );
+                
+                CopyArray<TOstComponent>(iOstComponents, iTmpArray);
+                CleanupComponentsArray(*iChangedArray);
+                RemoveComponentId(componentId, ETrue, *iTmpArray, *iChangedArray);
+                SetNewComponentsArrayPtr(iTmpArray);
+                
+                //notify internal listeners and update internal activation cache
+                HandleTraceActivationChanges(*iChangedArray);
+                NotifyInternalActivation( EFalse, componentId );
+                }
+        }
+
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTFRAME_EXIT_,"< DBTraceOstCategoryBitmap::ReadOstFrame position:%d", retPosition );
+    return retPosition;
+    }
+
+/**
+ * Read the groups from an OST frame
+ * 
+ * @param aMessage Received message
+ * @param aFrameStartIndex Start offset of the frame in message
+ * @param aActivationInfo Activation / deactivation flag
+ * @param aComponentIndex The index of the component where the groups belong to
+ * @param aComponentId The component ID
+ * @param aOstComponents Array with TOstComponent objects.
+ * @param aChangedArray Array with changed TOstComponent objects. 
+ * @return Offset after read frame
+ */
+TInt DBTraceOstCategoryBitmap::ReadOstFrameGroups(const TDesC8& aMessage, TInt aFrameStartIndex, TUint8 aActivationInfo,
+        TInt aComponentIndex, TUint32 aComponentId, RArray<TOstComponent>& aOstComponents, RArray< TOstComponent >& aChangedArray)
+    {
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTFRAMEGROUPS_ENTRY,"> DBTraceOstCategoryBitmap::ReadOstFrameGroups startIdx:%d componentIdx:%d", aFrameStartIndex, aComponentIndex );
+    
+    const TUint8* frameStart = aMessage.Ptr() + aFrameStartIndex;
+    TUint frameLen(aMessage.Length() - aFrameStartIndex);
+    TUint offset = KOstGroupIdOffset;
+    TInt retPosition( 0);
+    // One frame may contain multiple group ID's. Each occupy 2 bytes
+    TUint32 numberOfGroups = Read32(frameStart + KOstNumberOfGroupsOffset);
+
+    TUint i = 0;
+
+    // Number of groups in message is in Big Endian format so it need to be swap to Little Endian format
+    numberOfGroups = SWAP32( numberOfGroups );
+
+    if (frameLen >= (offset + numberOfGroups * KGroupIdLength ))
+        {
+        if (aActivationInfo == SOS_MON_TRACECORE_OST_OVERWRITE)
+            {
+            offset = OverwriteGroups(frameStart, aComponentIndex, aComponentId, numberOfGroups, aOstComponents, aChangedArray);
+            }
+        else
+            if (aActivationInfo == SOS_MON_TRACECORE_OST_DEACTIVATE || aActivationInfo == SOS_MON_TRACECORE_OST_ACTIVATE)
+                {
+                // Read Group ids and remove from array
+                for (i = 0; i < numberOfGroups; i++)
+                    {
+                    TUint16 groupId = Read16(frameStart + offset);
+                    // Group Id in message is in Big Endian format so it need to be swap to Little Endian format
+                    groupId = SWAP16( groupId );
+
+                    offset += KGroupIdLength;
+                    if (GroupIdIsValid(groupId)) 
+                    	{
+                        if (aActivationInfo == SOS_MON_TRACECORE_OST_ACTIVATE)
+                            {
+                            AddGroupId(aComponentId, groupId, aComponentIndex, aOstComponents, aChangedArray);
+                            }
+                        else
+                            {
+                            RemoveGroupId(aComponentId, groupId, aComponentIndex, aOstComponents, aChangedArray);
+                            }
+                    	}
+                    else
+                        {
+			            // Notifies activation interfaces of invalid group ID
+			            DTraceCore* traceCore = DTraceCore::GetInstance();
+			            if ( traceCore != NULL )
+			                {
+			                traceCore->GetNotifier().TraceError( aComponentId, groupId, KErrArgument );
+			                }
+                        }
+                    }
+                }
+            else
+                {
+                OstTrace1( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_READOSTFRAMEGROUPS__,"DBTraceOstCategoryBitmap::ReadOstFrameGroups - Unknow activation type %d", aActivationInfo);
+                }
+
+        // If all groups were removed from the component, it can also be removed
+        if ( ( (aActivationInfo == SOS_MON_TRACECORE_OST_DEACTIVATE ) || (aActivationInfo == SOS_MON_TRACECORE_OST_OVERWRITE ) )
+                && (aOstComponents[ aComponentIndex ].iGroups.Count() == 0 ))
+            {
+            RemoveComponentId(aComponentId, EFalse, aOstComponents, aChangedArray);
+            }
+        // The next frame offset is returned
+        retPosition = aFrameStartIndex + offset;
+        }
+    else
+        {
+        OstTraceExt2( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_READOSTFRAME_TOO_SHORT_FRAME,"DBTraceOstCategoryBitmap::ReadOstFrame - Too short frame nrOfGroups:%u len:%d",numberOfGroups, (TInt32)frameLen );
+        }
+    OstTrace1( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_READOSTFRAMEGROUPS_EXIT_,"< DBTraceOstCategoryBitmap::ReadOstFrameGroups position:%d", retPosition );
+    return retPosition;
+    }
+
+/**
+ * Callback when a trace activation message is received
+ *
+ * @param aMsg Reference to message
+ */
+void DBTraceOstCategoryBitmap::MessageReceived(TTraceMessage &aMsg)
+    {
+    TInt len(aMsg.iData->Length() );
+    
+    // Message header is in proprietary format
+    if (aMsg.iMsgFormat == EMessageHeaderFormatProprietary)
+        {
+        
+        // Check that message length is big enough 
+        if (len >= KOstMinFrameLength)
+            {
+            // Get OST message ID
+            TUint8 ostMessageId = *(aMsg.iData->Ptr() + KOstMessageIdOffset );
+            switch (ostMessageId)
+                {
+                case SOS_MON_TRACECORE_OST_ACTIVATION:
+                    {
+                    TInt nextFrameStart( 0);
+                    TInt lastFrameStart( -1);
+                    
+                    // Go through OST frames
+                    while (lastFrameStart < nextFrameStart)
+                        {
+                        lastFrameStart = nextFrameStart;
+                        nextFrameStart = ReadOstFrame( *aMsg.iData, nextFrameStart);
+                        }
+                    break;
+                    }
+                case SOS_MON_TRACECORE_OST_ACTIVATION_QUERY:
+                    {
+                    OstTrace0( TRACE_NORMAL, DBTRACEOSTCATEGORYBITMAP_MESSAGERECEIVED_ACTIVATION_QUERY_NOT_IMPLEMENTED,"DBTraceOstCategoryBitmap::MessageReceived - Activation query not implemented");
+                    break;
+                    }
+                default:
+                    {
+                    OstTrace1( TRACE_IMPORTANT , DBTRACEOSTCATEGORYBITMAP_MESSAGERECEIVED_INVALID_MESSAGE_ID,"DBTraceOstCategoryBitmap::MessageReceived - Invalid message ID - %d", ostMessageId);
+                    break;
+                    }
+                }
+            }
+        }
+    
+    // Message header is in OST format
+    else
+        if (aMsg.iMsgFormat == EMessageHeaderFormatOst)
+            {
+            OstProtocolMessage(aMsg);
+            }
+    }
+
+/**
+ * Ost Protocol Message handler
+ *
+ * @param aMessage The message
+ */
+void DBTraceOstCategoryBitmap::OstProtocolMessage(TTraceMessage &aMsg)
+    {
+    if ((*aMsg.iData)[OstHeader::OstTraceActivation::KOstHeaderMessageIdOffset-OstHeader::OstBaseProtocol::KOstBaseHeaderSize]
+            == OstConstants::OstTraceActivation::KSetApplicationStatusRequest)
+        {
+        ReadOstProtocolFrame( *aMsg.iData, 0);
+        
+        // Send KSetApplicationResponse
+        TBuf8<256> responseMessageHeader; // CodForChk_Dis_Magic
+        responseMessageHeader.Append(OstConstants::KOstHeaderVersion);
+        responseMessageHeader.Append(OstConstants::OstBaseProtocol::KOstTraceActivationProtocol); // 
+        responseMessageHeader.Append( 0); // Data size MSB
+        responseMessageHeader.Append( 4); // Data size LSB // CodForChk_Dis_Magic
+
+        TBuf8<256> responseMessageData; // CodForChk_Dis_Magic
+        TInt headerSize =
+             OstHeader::OstTraceActivation::KOstHeaderTransactionIdOffset-OstHeader::OstBaseProtocol::KOstBaseHeaderSize;
+        responseMessageData.Append((*aMsg.iData)[headerSize]);
+        responseMessageData.Append(OstConstants::OstTraceActivation::KSetApplicationStatusResponse);
+        responseMessageData.Append( 0x00); // Response request succeded TODO add constant to header
+        responseMessageData.Append( 0x00); // Filler
+
+        // Create TraceMessage
+        TTraceMessage msg;
+        msg.iMsgFormat = EMessageHeaderFormatOst;
+        msg.iHeader = &responseMessageHeader;
+        msg.iData = &responseMessageData;
+        msg.iMessageId = OstConstants::OstTraceActivation::KSetApplicationStatusResponse;
+        DTraceCoreActivationBase::SendResponse(msg);
+        }
+    }
+
+/**
+ * Overwite trace groups
+ *
+ * @param aComponentIndex The index of the component where the groups belong to
+ * @param aComponentId The component ID
+ * @param numberOfGroups Number of groups in overwrite message
+ * @param aOstComponents Array with TOstComponent objects.
+ * @param aChangedArray Array with changed TOstComponent objects.
+ * @return Offset after read frame
+ */
+TInt DBTraceOstCategoryBitmap::OverwriteGroups(const TUint8* aFrameStart, TInt aComponentIndex, TUint32 aComponentId,
+        TUint32 numberOfGroups, RArray<TOstComponent>& aOstComponents, RArray< TOstComponent >& aChangedArray)
+    {
+    OstTraceExt3( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_OVERWRITEGROUPS_ENTRY,"> DBTraceOstCategoryBitmap::OverwriteGroups. ComponentIdx:%d CID:0x%x NoOfGroups:%u",(TInt)aComponentIndex, (TUint)aComponentId , (TUint)numberOfGroups );
+    RArray<TUint> groupsInMessage;
+    TInt ret = 0;
+    TUint i = 0;
+    TUint offset = KOstGroupIdOffset;
+
+    // Read Group ids and remove from array
+    for (i = 0; i < numberOfGroups; i++)
+        {
+        TUint16 groupId = Read16(aFrameStart + offset);
+        // Group Id in message is in Big Endian format so it need to be swap to Little Endian format
+        groupId = SWAP16( groupId );
+
+        offset += KGroupIdLength;
+
+        ret = groupsInMessage.InsertInOrder(groupId);
+        }
+
+    
+    TUint numberOfGroupsInComponent = aOstComponents[ aComponentIndex ].iGroups.Count();
+    TUint numberOfRemovedGroups = 0;
+
+    // First remove those groups that are not any more activated
+    for (i = 0; i < numberOfGroupsInComponent; i++)
+        {
+
+        ret = groupsInMessage.FindInOrder(aOstComponents[ aComponentIndex ].iGroups[ i - numberOfRemovedGroups ]);
+
+        if (ret == KErrNotFound)
+            {
+            RemoveGroupId(aComponentId, aOstComponents[ aComponentIndex ].iGroups[ i - numberOfRemovedGroups ], aComponentIndex,
+                    aOstComponents, aChangedArray);
+            numberOfRemovedGroups++;
+            }
+        }
+
+    // Add groups that are not already added   
+    numberOfGroups = groupsInMessage.Count();
+    for (i = 0; i < numberOfGroups; i++)
+        {
+        ret = aOstComponents[ aComponentIndex ].iGroups.FindInOrder(groupsInMessage[ i ]);
+
+        if (ret == KErrNotFound)
+            {
+            if (GroupIdIsValid(groupsInMessage[ i ]))
+                {
+            
+                AddGroupId(aComponentId, groupsInMessage[ i ], aComponentIndex, aOstComponents, aChangedArray);
+                }
+            else
+                {
+                OstTrace1( TRACE_ERROR, DBTRACEOSTCATEGORYBITMAP_OVERWRITEGROUPS_ERROR, "DBTraceOstCategoryBitmap::OverwriteGroups - Invalid group ID: 0x%x", groupsInMessage[ i ] );
+                // Notifies activation interfaces of invalid group ID
+                DTraceCore* traceCore = DTraceCore::GetInstance();
+                if ( traceCore != NULL )
+                    {
+                    traceCore->GetNotifier().TraceError( aComponentId, groupsInMessage[ i ], KErrArgument );
+                    }
+                }            
+            }
+        }
+
+	groupsInMessage.Close();
+    OstTraceExt2( TRACE_FLOW, DBTRACEOSTCATEGORYBITMAP_OVERWRITEGROUPS_EXIT,"< DBTraceOstCategoryBitmap::OverwriteGroups. Offset:%u, ret:%d", offset, ret );
+    return offset;
+
+    }
+
+/**
+ * Checks if a component ID is supported by this activation object
+ * 
+ * @param aComponentID the component ID to be checked
+ * @return ETrue if supported, EFalse if not
+ */
+TBool DBTraceOstCategoryBitmap::IsComponentSupported(TUint32 /*aComponentID*/)
+    {
+    // All components are supported
+    return ETrue;
+    }
+
+/**
+ * Allocates memory for activation buffer
+ *
+ * @return KErrNone if allocation succesfull otherwise KErrNoMemory
+ */
+TInt DBTraceOstCategoryBitmap::AllocateActivationBuffer()
+	{  
+    TInt ret = KErrNone;
+    iActivationBuffer = ( TUint8* )Kern::Alloc( KMaxActivationBufferLength );
+    if ( iActivationBuffer == NULL )
+        {
+        ret = KErrNoMemory;
+        }
+    return ret;
+	}
+
+/**
+  * Read and write helper functions for activation buffer
+  */
+TUint32 DBTraceOstCategoryBitmap::Read32FromBuffer(TUint8*& aPtr)
+	{
+	TUint32 ret = 0;
+	if ( aPtr >= iActivationBuffer 
+		&& aPtr < iActivationBuffer+KMaxActivationBufferLength-K4Bytes)
+		{
+		ret = Read32(aPtr);
+		aPtr += K4Bytes;
+		}
+	return ret;
+	}
+
+TUint16 DBTraceOstCategoryBitmap::Read16FromBuffer(TUint8*& aPtr)
+	{
+	TUint16 ret = 0;
+	if ( aPtr >= iActivationBuffer 
+		&& aPtr < iActivationBuffer+KMaxActivationBufferLength-K2Bytes)
+		{
+		ret = Read16(aPtr);
+		aPtr += K2Bytes;
+		}
+	return ret;
+	}
+
+void DBTraceOstCategoryBitmap::WriteToBuffer(TUint8*& aPtr, TUint32 aData32)
+	{
+	if ( aPtr >= iActivationBuffer 
+		&& aPtr < iActivationBuffer+KMaxActivationBufferLength-K4Bytes)
+		{
+		*aPtr++ = aData32 & K8BitMask;
+		*aPtr++ = (aData32 >> K8BitShift) & K8BitMask;
+		*aPtr++ = (aData32 >> K16BitShift) & K8BitMask;
+		*aPtr++ = (aData32 >> K24BitShift) & K8BitMask;
+		}
+	}
+
+void DBTraceOstCategoryBitmap::WriteToBuffer(TUint8*& aPtr, TUint16 aData16)
+	{
+	if ( aPtr >= iActivationBuffer 
+		&& aPtr < iActivationBuffer+KMaxActivationBufferLength-K2Bytes)
+		{
+		*aPtr++ = aData16 & K8BitMask;
+		*aPtr++ = (aData16 >> K8BitShift) & K8BitMask;
+		}
+	}
+
+/**
+ * Handles trace activation changes
+ * 
+ * @pre On entry to this method writer mutex (iActivationWriteLock) must be help.
+ * @param aChangedArray Array with changed TOstComponent objects. 
+ */
+void DBTraceOstCategoryBitmap::HandleTraceActivationChanges(RArray< TOstComponent >& aChangedArray)
+    {
+    TC_TRACE( ETraceLevelFlow, Kern::Printf("Activated components count: %d", iOstComponents->Count()));
+    *(iBTraceOstCategoryHandler->iCacheItem1) = 0;
+    *(iBTraceOstCategoryHandler->iCacheItem2) = 0;
+    *(iBTraceOstCategoryHandler->iCacheItem3) = 0;
+    *(iBTraceOstCategoryHandler->iCacheItem4) = 0;
+    
+    TInt count = iOstComponents->Count();
+    // No traces activated, use Dummy handler    
+    if (count == 0)
+        {
+        iBTraceOstCategoryHandler->iAllTracesDeactivated = ETrue;
+        BTrace::SetHandler(DummyBTraceHandler);
+        TC_TRACE( ETraceLevelFlow, Kern::Printf("Dummy trace handler in use 1"));
+        }
+        
+    // Check if only printf traces are activated
+    else if (count == 1 && (*iOstComponents)[0].iComponentId == KKernelHooksOSTComponentUID)
+        {
+        	
+        // Check if there are other groups than printfs activated
+        RArray< TUint > groups = (*iOstComponents)[0].iGroups;
+        TInt groupcount = groups.Count();
+        TBool onlyPrintfs = ETrue;
+        for ( TInt i = 0; i < groupcount; ++i )
+            {
+            if (groups[i] > BTrace::EPlatsecPrintf)
+            	{
+            		onlyPrintfs = EFalse;
+            		break;
+            	}
+            }
+            
+        // If there are only printfs, keep using Dummy handler
+        if (onlyPrintfs)
+            {
+            iBTraceOstCategoryHandler->iAllTracesDeactivated = ETrue;
+            BTrace::SetHandler(DummyBTraceHandler);
+            TC_TRACE( ETraceLevelFlow, Kern::Printf("Dummy trace handler in use 2"));
+            }
+            
+        // Something else than printfs activated, use normal handler
+        else
+            {
+            iBTraceOstCategoryHandler->iAllTracesDeactivated = EFalse;
+            BTrace::SetHandler(oldHandler);
+            TC_TRACE( ETraceLevelFlow, Kern::Printf("Normal trace handler in use 1"));
+            }
+        }
+        
+    // More than 1 component activated, use normal handler
+    else
+        {
+        iBTraceOstCategoryHandler->iAllTracesDeactivated = EFalse;
+        BTrace::SetHandler(oldHandler);
+        TC_TRACE( ETraceLevelFlow, Kern::Printf("Normal trace handler in use 2"));
+        }
+    
+    
+    // Notify listeners about the changed groups
+    DTraceCore* traceCore = DTraceCore::GetInstance();
+    if ( traceCore != NULL )
+        {
+        count = aChangedArray.Count();
+        for (TInt i = 0; i < count; i++)
+            {
+            TUint32 componentId = aChangedArray[i].iComponentId;
+            RArray< TUint > groups = aChangedArray[i].iGroups;
+            TInt groupCount = groups.Count();
+            for (TInt j=0;j < groupCount;j++)
+                {
+                TUint32 group = groups[j];
+    
+                // Shift to be able to use IsTraceActivated function
+                if (IsTraceActivated(componentId, group << GRP_SHIFT))
+                    {
+                    traceCore->GetNotifier().TraceActivated(componentId, group);
+                    }
+                else
+                    {
+                    traceCore->GetNotifier().TraceDeactivated(componentId, group);
+                    }
+                }
+            }
+        }
+    }
+
+/**
+ * Gets activated groups for this component ID
+ * @param aComponentId the component ID
+ */
+RArray< TUint > DBTraceOstCategoryBitmap::GetActivatedGroups( const TUint32 aComponentId )
+    {
+    RArray< TUint > groups;
+    // Check index of component id in array
+    TInt index = FindComponentId(aComponentId, *iOstComponents);
+    if (index >= 0)
+        {
+        // Component id found, get groups
+        groups = (*iOstComponents)[ index ].iGroups;
+        }
+    return groups;
+    }
+
+/**
+ * Adds a group to array of changed activation groups
+ * @param aChangedArray Array with changed TOstComponent objects
+ * @param aComponentId Component ID
+ * @param aGroupId Group ID
+ */
+void DBTraceOstCategoryBitmap::AddGroupToChangedArray(RArray< TOstComponent >& aChangedArray, TUint32 aComponentId, TGroupId aGroupId)
+    {
+    TOstComponent newComponent;
+    newComponent.iComponentId = aComponentId;
+    aChangedArray.InsertInUnsignedKeyOrder(newComponent);
+    TInt changedIndex = FindComponentId(aComponentId, aChangedArray);
+    if(changedIndex != KErrNotFound)
+        aChangedArray[ changedIndex ].iGroups.InsertInOrder(aGroupId);
+    }
+
+/**
+* Utility method to copy data between two RArray objects.
+*/
+template <class T>
+void DBTraceOstCategoryBitmap::CopyArray(RArray<T>* aSrc, RArray<T>* aDst)
+    {
+    aDst->Reset();
+    TInt c = aSrc->Count();
+    for(TInt i=0; i<c; ++i)
+        aDst->Append( (*aSrc)[i] );
+    }
+
+
+//TODO: use this doxygen comment instead of old one
+//TODO: don't pass any args as swap occurs only between iOstComponents and tmpArray
+/**
+ * Sets new pointer for array with activated components.
+ * This operation is protected by spin lock on SMP systems.
+ * 
+ * @param aNewPtr Pointer to new array containing TOstComponent objects.
+ */
+void DBTraceOstCategoryBitmap::SetNewComponentsArrayPtr(RArray<TOstComponent>*& aNewPtr)
+    {
+    TInt irq = ReadLock();
+    RArray<TOstComponent>* tmpPtr = iOstComponents;
+    iOstComponents = aNewPtr;
+    aNewPtr = tmpPtr;
+    ReadUnlock(irq);
+    }
+
+/**
+ * Internal method to destroy array used to store activated components.
+ */
+void DBTraceOstCategoryBitmap::CleanupComponentsArray(RArray< TOstComponent >& aComponentArray)
+    {
+    TInt componentCount = aComponentArray.Count();
+    for (TInt i=0; i<componentCount; i++)
+        {
+        aComponentArray[i].iGroups.Reset();
+        }
+    aComponentArray.Reset();
+    }
+
+/**
+ * Internal method to destroy arrays used to store activated components.
+ */
+void DBTraceOstCategoryBitmap::CleanupComponentsArrays()
+    {
+    if(iOstComponents)
+        {
+        CleanupComponentsArray(*iOstComponents);
+        iOstComponents->Close();
+        Kern::Free(iOstComponents);
+        iOstComponents = NULL;
+        }
+        
+    if(iTmpArray)
+        {
+        CleanupComponentsArray(*iTmpArray);
+        iTmpArray->Close();
+        Kern::Free(iTmpArray);
+        iTmpArray = NULL;
+        }
+    
+    if (iChangedArray)
+        {
+        CleanupComponentsArray(*iChangedArray);
+        iChangedArray->Close();
+        Kern::Free(iChangedArray);
+        iChangedArray = NULL;
+        }
+    }
+    
+/**
+ * Reactivate all currently activated traces
+ *
+ * @return KErrNone if refresh successful
+ */
+TInt DBTraceOstCategoryBitmap::RefreshActivations()
+    {
+    RArray< TOstComponent >* tmpArray = new RArray<TOstComponent>(KOstComponentsArrayGranularity);
+    if(!tmpArray)
+        return KErrNoMemory;
+
+    CopyArray<TOstComponent>(iOstComponents, tmpArray);
+    // Go through all components in array and refresh activations for each
+    TInt componentCount = tmpArray->Count();
+    for (TInt i=0; i<componentCount; i++)
+        {
+        TUint32 componentId = (*tmpArray)[ i ].iComponentId;
+        RArray< TUint > groups = (*tmpArray)[ i ].iGroups;
+        // Go through all groups for this component and refresh activations for each
+        TInt groupCount = groups.Count();
+        for (TInt j=0; j<groupCount; j++)
+            {
+            TUint groupId = groups[ j ];
+            // Don't refresh EMetaTrace as this messes up the meta traces outputted
+            if (componentId != KKernelHooksOSTComponentUID || groupId != BTrace::EMetaTrace)
+                {
+                DeactivateTrace(componentId, groupId);
+                ActivateTrace(componentId, groupId);
+                }
+            }
+        }
+    tmpArray->Close();
+    Kern::Free(tmpArray);
+    return KErrNone;
+    }
+
+// End of File