tracesrv/tracecore/btrace_handler/test/d_tracecore/src/d_tracecore.cpp
changeset 56 aa2539c91954
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecore/btrace_handler/test/d_tracecore/src/d_tracecore.cpp	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,508 @@
+// Copyright (c) 2005-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:
+// e32test\debug\d_tracecore.cpp
+// 
+//
+
+#include <kernel/kern_priv.h>
+#include <kernel/kernel.h>
+
+#include <e32btrace.h>
+#include <opensystemtrace_types.h>
+
+#ifndef __SMP__
+#include <nkern/nkern.h>
+#else
+#include <nkernsmp/nkern.h>
+#endif //__SMP__
+#include <TraceCoreTraceActivationIf.h>
+#include <TraceCoreNotificationReceiver.h>
+#include "TraceCore.h"
+#include "d_tracecore.h"
+
+
+#include "TraceCoreTestWriter.h"
+#include "TestDataWriterNotifier.h"
+
+const TInt KFrameBufferLength = 4096;
+
+class DTraceCoreTestFactory : public DLogicalDevice 
+	{
+public:
+	virtual TInt Install();
+	virtual void GetCaps(TDes8& aDes) const;
+	virtual TInt Create(DLogicalChannelBase*& aChannel);
+	};
+
+class DTraceCoreTestChannel : public DLogicalChannel, MTestWriterNotifier, MTraceCoreNotificationReceiver
+	{
+public:
+	DTraceCoreTestChannel();
+	virtual ~DTraceCoreTestChannel();
+	//	Inherited from DObject
+	virtual TInt RequestUserHandle(DThread* aThread, TOwnerType aType);
+	// Inherited from DLogicalChannelBase
+	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual void HandleMsg(TMessageBase* aMsg);
+	TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
+	TInt DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+	
+    // Virtual from MTraceCoreNotificationReceiver. Called from TraceCore.
+    void TraceActivated( TUint32 aComponentId, TUint16 aGroupId  );
+    void TraceDeactivated( TUint32 aComponentId, TUint16 aGroupId  );
+	
+
+private:
+	DThread* iClient;
+	
+private:
+	void ActivateTrace(TcDriverParameters& aDriverParameters, TInt aNumTraces);
+	void DeactivateTrace(TcDriverParameters& aDriverParameters, TInt aNumTraces);
+    TInt RefreshActivations();
+    TInt ValidateFilterSync(TcDriverParameters& aDriverParams);
+    void DropNextTrace(TBool aDrop);
+    void RegisterActivationNotification(TcDriverParameters& aDriverParameters, TBool aRegister);
+    TInt CheckActivationNotificationOk(TBool aShouldBeNotified);
+	
+	TInt CreateWriter();
+	// from MTestWriterNotifier
+    virtual void WriteComplete(TNotifyData aData);
+    virtual void WriteStart();
+private:
+  
+    TRequestStatus* iTraceDataRequestStatus;      // request status for asynct trace requests
+    TDes8*          iTraceDataDestination;        // pointer to write trace data to
+    TDynamicDfcQue* iOstTestDriverDfcQ;           // Dedicated non-realtime DfcQ
+    TBool           iDropTrace;                   // if test doesn't want trace to actually be sent
+    TInt                            iFrameCount;  // Number of frames to capture before notify is issued 
+    TBuf8<KFrameBufferLength>       iFrameBuffer; // the frame buffer
+    TBool           iFilterInSyncWhenNotified;    // If true, filter in TraceCore was in sync with the notification
+    TBool           iNotificationReceived;        // If true, trace activation notification was received
+	};
+
+const TInt KTestOstDriverThreadPriority = 24;
+_LIT(KTestOstDriverThread,"d_tracecore_dfcq");
+
+
+//
+// DTraceCoreTestFactory
+//
+
+TInt DTraceCoreTestFactory::Install()
+	{
+	return SetName(&RTraceCoreTest::Name());
+	}
+
+void DTraceCoreTestFactory::GetCaps(TDes8& aDes) const
+	{
+	Kern::InfoCopy(aDes,0,0);
+	}
+
+TInt DTraceCoreTestFactory::Create(DLogicalChannelBase*& aChannel)
+	{
+	aChannel=new DTraceCoreTestChannel();
+	if(!aChannel)
+		return KErrNoMemory;
+	return KErrNone;
+	}
+
+
+//
+// DTraceCoreTestChannel
+//
+
+DTraceCoreTestChannel::DTraceCoreTestChannel()
+: iTraceDataRequestStatus(NULL)
+, iTraceDataDestination(NULL)
+, iDropTrace(EFalse)
+, iFilterInSyncWhenNotified(EFalse)
+    {
+	}
+
+DTraceCoreTestChannel::~DTraceCoreTestChannel()
+	{	
+	// Detatch (stop notifications) from writer	     
+    DTraceCoreTestWriter* testWriter = DTraceCoreTestWriter::GetInstance();
+    if(testWriter)
+        {
+        testWriter->SetNotifier(NULL);        
+        }           
+    delete testWriter;
+    
+    //destroy dfcq
+    if (iOstTestDriverDfcQ)
+        {
+        iOstTestDriverDfcQ->Destroy();
+        }
+	}
+
+TInt DTraceCoreTestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
+	{
+    TDynamicDfcQue* q;
+    TInt ret = Kern::DynamicDfcQCreate(q, KTestOstDriverThreadPriority , KTestOstDriverThread);
+    if (ret==KErrNone)
+        {
+        //disable real-time state of the dfcq
+        q->SetRealtimeState(ERealtimeStateOff);
+        iOstTestDriverDfcQ=q;
+        SetDfcQ(iOstTestDriverDfcQ);
+        iMsgQ.Receive();
+        }
+    else
+        {
+        Kern::Printf("Kern::DynamicDfcQCreate returned with error: %d",ret);
+        return ret;
+        }
+	iClient = &Kern::CurrentThread();			
+	return CreateWriter();
+	}
+
+void DTraceCoreTestChannel::WriteStart()
+    {
+    }
+
+void DTraceCoreTestChannel::WriteComplete(TNotifyData aNotifyData) 
+    {
+
+    if(iTraceDataRequestStatus && iFrameCount > 0 )
+        {    
+
+        // append the data into the frame buffer if it fits
+        if( iFrameBuffer.Length() + aNotifyData.iLen < KFrameBufferLength)
+            {        
+            iFrameBuffer.Append(TPtrC8((TUint8*)aNotifyData.iAddr, aNotifyData.iLen ));
+            }
+        else
+            {
+            // force a send of what we have
+            iFrameCount = 1;
+            }
+                       
+        if( --iFrameCount == 0)
+            {    
+            if (iDropTrace)
+                {
+                // test client is requesting we force tracecore to drop the next trace
+                // so we call the same function that a writer would call ( SetPreviousTraceDropped )
+                // in order to notify tracecore that a trace has been dropped            
+                DTraceCore* tracecore = DTraceCore::GetInstance();
+                tracecore->SetPreviousTraceDropped(ETrue);
+                }
+            else//send the trace
+                {
+                Kern::KUDesPut(*iTraceDataDestination,iFrameBuffer);
+                }
+            
+            // complete the clients request
+            Kern::RequestComplete(iTraceDataRequestStatus, 0);
+            iTraceDataRequestStatus = NULL;
+            iFrameBuffer.Zero();            
+            }
+        }    
+    }
+
+TInt DTraceCoreTestChannel::CreateWriter()
+    {
+    TInt r = KErrNoMemory;
+    DTraceCoreTestWriter* testWriter = DTraceCoreTestWriter::GetInstance(); 
+    if(testWriter)
+        {
+        r = KErrNone;
+        testWriter->SetNotifier(this);
+        }       
+    return r;
+    }
+
+TInt DTraceCoreTestChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
+	{
+	if (aType!=EOwnerThread || aThread!=iClient)
+		return KErrAccessDenied;
+	return KErrNone;
+	}
+
+void DTraceCoreTestChannel::HandleMsg(TMessageBase* aMsg)
+	{    
+    TThreadMessage& msg = *(static_cast<TThreadMessage*>(aMsg));    
+    TInt id = msg.iValue;
+    
+    if ( id == static_cast<TInt>( ECloseMsg ) )
+        {
+
+        // Don't receive any more messages
+        msg.Complete( KErrNone, EFalse );
+
+        // Complete all outstanding messages on this queue
+        iMsgQ.CompleteAll( KErrServerTerminated );
+        }
+    else if ( id == KMaxTInt )
+        {
+        // 'DoCancel' message
+        TRequestStatus* pS = reinterpret_cast<TRequestStatus*>( msg.Ptr0() );
+        Kern::RequestComplete(iClient,pS,KErrCancel);
+        msg.Complete( KErrNone, ETrue );
+        }
+    else if ( id < 0 )
+        {
+        // DoRequest
+        TRequestStatus* pS = reinterpret_cast<TRequestStatus*>( msg.Ptr0() );
+        
+        TInt ret = DoRequest( ~id, pS, msg.Ptr1(), msg.Ptr2());
+        if ( ret != KErrNone )
+            {
+            Kern::RequestComplete( iClient, pS, ret );
+            }//noelse
+        
+        msg.Complete( KErrNone, ETrue );
+        }
+    else
+        {
+        // DoControl
+        TInt ret = DoControl( id, msg.Ptr0(), msg.Ptr1() );
+        msg.Complete( ret, ETrue );
+        }
+
+	}
+
+TInt DTraceCoreTestChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+    {
+    switch(aFunction)
+          {
+    // test functions
+          case RTraceCoreTest::EActivateTrace:
+              {
+//            Kern::Printf("DTraceCoreTestChannel::DoControl() RTraceCoreTest::EActivateTrace");
+              TcDriverParameters* tcDriverParameters = static_cast<TcDriverParameters*>(a1); 
+              __ASSERT_ALWAYS(tcDriverParameters!=NULL, Kern::Fault("DTraceCoreTestChannel::DoControl: NULL parameter!", __LINE__) );
+              ActivateTrace(*tcDriverParameters, (TInt)(a2));
+              return KErrNone;
+              }
+         case RTraceCoreTest::EDeactivateTrace:
+              {
+//            Kern::Printf("DTraceCoreTestChannel::DoControl()  RTraceCoreTest::EDeactivateTrace");
+              TcDriverParameters* tcDriverParameters = static_cast<TcDriverParameters*>(a1); 
+              __ASSERT_ALWAYS(tcDriverParameters!=NULL, Kern::Fault("DTraceCoreTestChannel::DoControl: NULL parameter!", __LINE__) );              
+              DeactivateTrace(*tcDriverParameters, (TInt)(a2));
+              return KErrNone;
+              }
+         case RTraceCoreTest::ERefreshActivations:
+             {
+//            Kern::Printf("DTraceCoreTestChannel::DoControl() RTraceCoreTest::ERefreshActivations");
+             return RefreshActivations();
+             }
+              
+         case RTraceCoreTest::EValidateFilterSync:
+             {
+//           Kern::Printf("DTraceCoreTestChannel::ReqDoControluest()  RTraceCoreTest::EValidateFilterSync");
+             TcDriverParameters* tcDriverParameters = static_cast<TcDriverParameters*>(a1); 
+             __ASSERT_ALWAYS(tcDriverParameters!=NULL, Kern::Fault("DTraceCoreTestChannel::DoControl: NULL parameter!", __LINE__) );             
+             return ValidateFilterSync(*tcDriverParameters);
+             }
+             
+         case RTraceCoreTest::EDropNextTrace:
+             {
+//           Kern::Printf("DTraceCoreTestChannel::DoControl()  RTraceCoreTest::EDropNextTrace");        
+             DropNextTrace(TBool(a1));
+             return KErrNone;
+             }
+         case RTraceCoreTest::ERegisterActivationNotification:
+             {
+//           Kern::Printf("DTraceCoreTestChannel::DoControl()  RTraceCoreTest::ERegisterActivationNotification");
+             TcDriverParameters* tcDriverParameters = static_cast<TcDriverParameters*>(a1); 
+             __ASSERT_ALWAYS(tcDriverParameters!=NULL, Kern::Fault("DTraceCoreTestChannel::DoControl: NULL parameter!", __LINE__) );
+             RegisterActivationNotification(*tcDriverParameters, (TBool)(a2));
+             return KErrNone;
+             }       
+         case RTraceCoreTest::ECheckActivationNotificationOk:
+             {
+//             Kern::Printf("DTraceCoreTestChannel::DoControl()  RTraceCoreTest::ECheckActivationNotificationOk");        
+             return CheckActivationNotificationOk((TBool)(a1));
+             }                  
+            
+         default:
+             break;
+              }
+    return KErrNotSupported;
+    }
+
+TInt DTraceCoreTestChannel::DoRequest(TInt aId, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+    {
+    switch(aId)
+        {
+        case RTraceCoreTest::ERequestTraceData:  // async request
+            {                     
+            iTraceDataRequestStatus   = aStatus;           
+            if(a1)
+                {
+                TDes8* p = NULL;
+                XTRAPD(r, XT_DEFAULT, kumemget(&p, &a1, sizeof(TAny*)); )                
+                iTraceDataDestination = (r == KErrNone) ? p : NULL;                
+                }
+            
+            iFrameCount = (a2) ? (TInt)a2 : 1;
+            iFrameBuffer.Zero();
+            
+            return KErrNone;
+                }
+          
+         default:
+            break;
+        }
+    return KErrNotSupported;
+    }
+
+void DTraceCoreTestChannel::ActivateTrace(TcDriverParameters& aDriverParameters, TInt aNumTraces)
+    {
+    TcDriverParameters tcDriverParams;
+    TInt ret = Kern::ThreadRawRead(iClient, (const TAny *)&aDriverParameters,(TAny*)&tcDriverParams, sizeof(TcDriverParameters) );
+    __ASSERT_ALWAYS(KErrDied!=ret, Kern::Fault("DTraceCoreTestChannel::ActivateTrace: ThreadRawRead: iClient died!", __LINE__) );    
+    
+    NKern::ThreadEnterCS();
+    for (TInt i=0; i<aNumTraces; i++)
+        {
+        DTraceActivationIf::ActivateTrace((tcDriverParams.iComponentId)+i,(tcDriverParams.iGroupId)+i);
+        }
+    NKern::ThreadLeaveCS();    
+    }
+
+void DTraceCoreTestChannel::DeactivateTrace(TcDriverParameters& aDriverParameters, TInt aNumTraces)
+    {    
+    TcDriverParameters tcDriverParams;    
+    TInt ret = Kern::ThreadRawRead(iClient, (const TAny *)&aDriverParameters,(TAny*)&tcDriverParams, sizeof(TcDriverParameters) );
+    __ASSERT_ALWAYS(KErrDied!=ret,Kern::Fault("DTraceCoreTestChannel::DeactivateTrace: ThreadRawRead: iClient died!", __LINE__) );
+
+    NKern::ThreadEnterCS();    
+    for (TInt i=0; i<aNumTraces; i++)
+        {
+        DTraceActivationIf::DeactivateTrace((tcDriverParams.iComponentId)+i,(tcDriverParams.iGroupId)+i);
+        }
+    NKern::ThreadLeaveCS();    
+    }
+
+TInt DTraceCoreTestChannel::RefreshActivations()
+    {
+    NKern::ThreadEnterCS();
+    TInt err = DTraceActivationIf::RefreshActivations();
+    NKern::ThreadLeaveCS();
+    return err;
+    }
+
+/**
+ * Validate that the BTrace::Filter matches the tracecore filters 
+ * for all OST categories
+ * 
+ * returns KErrNone if filters match - KErrGeneral otherwise
+ */
+TInt  DTraceCoreTestChannel::ValidateFilterSync(TcDriverParameters& aDriverParameters)
+    {
+    TcDriverParameters tcDriverParams;
+    TInt ret = Kern::ThreadRawRead(iClient, (const TAny *)&aDriverParameters,(TAny*)&tcDriverParams, sizeof(TcDriverParameters) );
+    __ASSERT_ALWAYS(ret == KErrNone, Kern::Fault("DTraceCoreTestChannel::ValidateFilterSync: ThreadRawRead: iClient died!", __LINE__) );    
+    
+    TBool tcFilter = DTraceActivationIf::IsTraceActivated(tcDriverParams.iComponentId, tcDriverParams.iGroupId);
+    TBool btFilter = BTrace::CheckFilter(tcDriverParams.iGroupId);                    
+    if( tcFilter != btFilter)
+        {
+        ret = KErrGeneral;
+        }            
+
+    return ret;
+    }
+
+/**
+ * Adds or removes a activation notification listener
+ * 
+ * returns KErrNone if filters match - KErrGeneral otherwise
+ */
+void DTraceCoreTestChannel::RegisterActivationNotification(TcDriverParameters& aDriverParameters, TBool aRegister)
+    {
+    TcDriverParameters tcDriverParams;
+    TInt ret = Kern::ThreadRawRead(iClient, (const TAny *)&aDriverParameters,(TAny*)&tcDriverParams, sizeof(TcDriverParameters) );
+    __ASSERT_ALWAYS(ret == KErrNone, Kern::Fault("DTraceCoreTestChannel::ValidateFilterSync: ThreadRawRead: iClient died!", __LINE__) );
+        
+    if (aRegister)
+        {
+        MTraceCoreNotificationReceiver::RegisterNotificationReceiver(tcDriverParams.iComponentId, tcDriverParams.iGroupId);
+        }
+    else
+        {
+        MTraceCoreNotificationReceiver::UnregisterNotificationReceiver(tcDriverParams.iComponentId, tcDriverParams.iGroupId);
+        }
+    }
+
+/**
+ * Add a activation notification listener, then activate a trace group and check if the activation  
+ * has really happened when the notification arrives
+ * 
+ * returns KErrNone if filters match - KErrGeneral otherwise
+ */
+TInt DTraceCoreTestChannel::CheckActivationNotificationOk(TBool aShouldBeNotified)
+    {
+    TInt ret = KErrGeneral;
+    
+    // Everything OK if we should've got notification and we got and filters were in sync
+    if (aShouldBeNotified && iNotificationReceived && iFilterInSyncWhenNotified)
+        {
+        ret = KErrNone;
+        }
+    
+    // Everything OK if we should NOT got notification and we didn't
+    else if (!aShouldBeNotified && !iNotificationReceived)
+        {
+        ret = KErrNone;
+        }
+    
+    // Reset the variables for next test
+    iFilterInSyncWhenNotified = EFalse;
+    iNotificationReceived = EFalse;
+    
+    return ret;
+    }
+
+/**
+ * Callback function from TraceCore when the trace is activated
+ */
+void DTraceCoreTestChannel::TraceActivated( TUint32 aComponentId, TUint16 aGroupId  )
+    {
+    TBool tcFilter = DTraceActivationIf::IsTraceActivated(aComponentId, aGroupId);
+    iFilterInSyncWhenNotified = tcFilter;
+    iNotificationReceived = ETrue;
+    }
+
+/**
+ * Callback function from TraceCore when the trace is deactivated
+ */
+void DTraceCoreTestChannel::TraceDeactivated( TUint32 aComponentId, TUint16 aGroupId  )
+    {
+    TBool tcFilter = DTraceActivationIf::IsTraceActivated(aComponentId, aGroupId);
+    iFilterInSyncWhenNotified = !tcFilter;
+    iNotificationReceived = ETrue;
+    }
+
+/*
+ * Tells the test writer that we don't actually want to 
+ * send a trace... this is to test that the handlers
+ * are formatting the data to include "missing" info.
+ */
+void DTraceCoreTestChannel::DropNextTrace(TBool aDrop)
+    {
+    iDropTrace=aDrop;
+    }
+
+DECLARE_STANDARD_LDD()
+	{
+	Kern::Printf("d_tracecore.ldd creating DTraceCoreTestFactory");
+	return new DTraceCoreTestFactory;
+	}
+
+