--- /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;
+ }
+
+