piprofiler/plugins/BUPplugin/src/BupPlugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 16:17:58 +0300
branchRCL_3
changeset 59 8ad140f3dd41
parent 49 7fdc9a71d314
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  
*
*/

 
#include "BupPlugin.h"	
//#include <piprofiler/EngineUIDs.h>

#include <w32std.h> 	// for listening key events

	
// LITERALS
// CONSTANTS
const TUid KSamplerBupPluginUid = { 0x2001E5B6 };

/*
 *	
 *	class CBupPlugin implementation
 * 
 */

CBupPlugin* CBupPlugin::NewL(const TUid /*aImplementationUid*/, TAny* /*aInitParams*/)
	{
	LOGTEXT(_L("CBupPlugin::NewL() - entry"));
    CBupPlugin* self = new (ELeave) CBupPlugin();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
	LOGTEXT(_L("CBupPlugin::NewL() - exit"));
    return self;
	}

CBupPlugin::CBupPlugin() :
	iVersionDescriptor(&(this->iVersion[1]),0,19), 	
	iSamplerType(PROFILER_USER_MODE_SAMPLER)
	{
	iSamplerId = PROFILER_BUP_SAMPLER_ID;
    iEnabled = EFalse;
	LOGTEXT(_L("CBupPlugin::CBupPlugin() - konstruktori"));
	}

void CBupPlugin::ConstructL() 
	{
	LOGTEXT(_L("CBupPlugin::ConstructL() - entry"));
	
	// initiate sampler attributes array
	iSamplerAttributes = new(ELeave) CArrayFixFlat<TSamplerAttributes>(1); // only one sampler
	
	// insert default attributes to array
	InitiateSamplerAttributesL();
	
	LOGTEXT(_L("CBupPlugin::ConstructL() - exit"));
	}


CBupPlugin::~CBupPlugin()
	{
	LOGTEXT(_L("CBupPlugin::~CBupPlugin() - entry"));
	if(iButtonListener)
	    {
	    // check if button listener still running
	    if(Enabled())
	        {
	        // stop profiling
	        iButtonListener->Stop();
	        }
        delete iButtonListener;
	    }
	
	if(iSamplerAttributes)
	    {
	    iSamplerAttributes->Reset();
	    }
    delete iSamplerAttributes;
	
	LOGTEXT(_L("CBupPlugin::~CBupPlugin() - exit"));
	}

TUid CBupPlugin::Id(TInt /*aUid*/) const
	{
    LOGSTRING2("CBupPlugin::Id():0x%X", KSamplerBupPluginUid.iUid );
    return KSamplerBupPluginUid;
	}

void CBupPlugin::InitiateSamplerAttributesL()
    {
    // create sampler attribute container
    TSamplerAttributes attr(KSamplerBupPluginUid.iUid,
            KBUPShortName(),
            KBUPLongName(),
            KBUPDescription(),
            -1,
            ETrue,
            EFalse,
            0); // default item count
    this->iSamplerAttributes->AppendL(attr);
    }

// returns setting array
void CBupPlugin::GetAttributesL(CArrayFixFlat<TSamplerAttributes>* aAttributes)
    {
    // append my own attributes to complete array, requested by profiler engine
    aAttributes->AppendL(iSamplerAttributes->At(0));
    }

TInt CBupPlugin::SetAttributesL(TSamplerAttributes aAttributes)
    {
    TSamplerAttributes attr;

    attr = iSamplerAttributes->At(0);
    // if UIDs match replace the old 
    if(attr.iUid == aAttributes.iUid)
        {
        // replace the old attribute container
        iSamplerAttributes->Delete(0);
        iSamplerAttributes->InsertL(0, aAttributes);
        return KErrNone;
        }
    return KErrNotFound;
    }

/* 
 * Method for parsing and transforming text array settings into TSamplerAttributes (per each sub sampler),
 * called by CSamplerController class
 * 
 * @param array of raw text setting lines, e.g. [gpp]\nenabled=true\nsampling_period_ms=1\n
 */
TInt CBupPlugin::ConvertRawSettingsToAttributes(CDesC8ArrayFlat* aAllSettingsArray)
    {
    // local literals
    _LIT8(KBUPShort, "bup");

    TInt err(KErrNone);
    TBuf8<16> samplerSearchName;
    samplerSearchName.Copy(KBUPShort);
    
    // get sampler specific settings  
    err = DoSetSamplerSettings(aAllSettingsArray, samplerSearchName, 0);
    
    // returns KErrNone if settings found, otherwise KErrNotFound
    return err;
    }

TInt CBupPlugin::DoSetSamplerSettings(CDesC8ArrayFlat* aAllSettings, TDesC8& aSamplerName, TInt aIndex)
    {
    // 
    TBuf8<16> samplerSearch;
    samplerSearch.Copy(KBracketOpen);
    samplerSearch.Append(aSamplerName);
    samplerSearch.Append(KBracketClose);
    
    // read a line
    for (TInt i(0); i<aAllSettings->MdcaCount(); i++)
        {
        // check if this line has a setting block start, i.e. contains [xxx] in it
        if (aAllSettings->MdcaPoint(i).CompareF(samplerSearch) == 0)
            {
            // right settings block found, now loop until the next block is found
            for(TInt j(i+1);j<aAllSettings->MdcaCount();j++)
                {
                // check if the next settings block was found
                if(aAllSettings->MdcaPoint(j).Left(1).CompareF(KBracketOpen) != 0)
                    {
                    // save found setting value directly to its owners attributes
                    SaveSettingToAttributes(aAllSettings->MdcaPoint(j), aIndex);
                    }
                else
                    {
                    // next block found, return KErrNone
                    return KErrNone;
                    }
                }
            }
        }
    
    return KErrNotFound;
    }

/**
 * Method for setting a specific descriptor (from settings file) to attribute structure
 * 
 * @param aSetting  
 * @param aName  
 */
void CBupPlugin::SaveSettingToAttributes(const TDesC8& aSetting, TInt aIndex)
    {
    // find the equal mark from the setting line
    TInt sepPos = aSetting.Find(KSettingItemSeparator);
    // check that '=' is found
    if (sepPos > 0)
        {
        // check that the element matches
        if (aSetting.Left(sepPos).CompareF(KEnabled) == 0)
            {
            TBool en;
            CSamplerPluginInterface::Str2Bool(aSetting.Right(aSetting.Length()-sepPos-1), en);
            if(iSamplerAttributes->At(aIndex).iEnabled != en)
                {
                iSamplerAttributes->At(aIndex).iEnabled = en;
                }
            }
        }
    }

TInt CBupPlugin::GetSamplerType()
	{
	return iSamplerType;
	}

TInt CBupPlugin::ResetAndActivateL(CProfilerSampleStream& aStream) 
	{
	LOGTEXT(_L("CBupPlugin::ResetAndActivate() - entry"));
	TInt ret(KErrNone);
	
	// check if sampler enabled
	if(iSamplerAttributes->At(0).iEnabled)
	    {
        // create first the listener instance
        iButtonListener = CProfilerButtonListener::NewL(this);
        
        LOGTEXT(_L("CBupPlugin::ResetAndActivate() - listener created"));
        
        iStream = &aStream;
        TInt length = this->CreateFirstSample();
        iVersion[0] = (TUint8)length;
        LOGSTRING2("CBupPlugin::ResetAndActivate() - AddSample, length %d",length);
        ret = AddSample(iVersion, length+1, 0);
        if(ret != KErrNone)
            return ret;
        
        // activate button listener
        ret = iButtonListener->StartL();

        iEnabled = ETrue;
        
        LOGTEXT(_L("CBupPlugin::ResetAndActivate() - exit"));
	    }
	return ret;

	}
	
TInt CBupPlugin::CreateFirstSample()
	{
	LOGTEXT(_L("CBupPlugin::CreateFirstSample - entry"));
	this->iVersionDescriptor.Zero();
	this->iVersionDescriptor.Append(_L8("Bappea_BUP_V"));
	this->iVersionDescriptor.Append(PROFILER_BUP_SAMPLER_VERSION);
	LOGTEXT(_L("CBupPlugin::CreateFirstSample - exit"));
	return (TInt)(this->iVersionDescriptor.Length());
	}

TInt CBupPlugin::StopSampling() 
	{
	if(iButtonListener)
		{
		iButtonListener->Stop();
		delete iButtonListener;	// delete listener after every trace
		iButtonListener = NULL;
		}
	
    // set disabled
    iEnabled = EFalse;

	return KErrNone;
	}

void CBupPlugin::FillThisStreamBuffer(TBapBuf* /*aBapBuf*/, TRequestStatus& /*aStatus*/)
	{
	}

/*
 * 
 * Implementation of class CProfilerButtonListener
 * 
 */
CProfilerButtonListener::CProfilerButtonListener(CBupPlugin* aSampler) 
	{
	LOGTEXT(_L("CProfilerButtonListener::CProfilerButtonListener() - konstuktori"));
	this->iSampler = aSampler;
	iSampleStartTime = 0;
	LOGTEXT(_L("CProfilerButtonListener::CProfilerButtonListener() - konstuktori exit"));
	}

CProfilerButtonListener* CProfilerButtonListener::NewL(CBupPlugin* aSampler)
	{
	LOGTEXT(_L("CProfilerButtonListener::NewL() - entry"));
	CProfilerButtonListener* self = new (ELeave) CProfilerButtonListener(aSampler);
	CleanupStack::PushL( self );
	self->ConstructL();
	CleanupStack::Pop();
	LOGTEXT(_L("CProfilerButtonListener::NewL() - exit"));
	return self;
	}

CProfilerButtonListener::~CProfilerButtonListener() 
	{
	LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener() - entry af"));

	if(iMainWindow)
		{
		LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener(): flushing iWs"));
		iWs.Flush();
		LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener(): finishing"));
		}
	delete iMainWindow;
	LOGTEXT(_L("CProfilerButtonListener::~CProfilerButtonListener() - exit"));
	}
	
void CProfilerButtonListener::ConstructMainWindowL()
	{
    LOGTEXT(_L("CProfilerButtonListener::ConstructMainWindowL() - Entry"));

    CWindow* window = new (ELeave) CWindow(this);
    CleanupStack::PushL( window );
	window->ConstructL(TRect(TPoint(0,0), TSize(0,0)));
    delete iMainWindow;
    iMainWindow = window;
    CleanupStack::Pop( window );
	
    LOGTEXT(_L("CProfilerButtonListener::ConstructMainWindowL() - Exit"));
	}

void CProfilerButtonListener::HandleKeyEventL (TKeyEvent& /*aKeyEvent*/)
    {
    LOGTEXT(_L("CProfilerButtonListener::HandleKeyEventL() - Start"));
    LOGTEXT(_L("CProfilerButtonListener::HandleKeyEventL() - End"));
	}


TInt CProfilerButtonListener::RunError(TInt aError)
    {
    // get rid of everything we allocated
    // deactivate the anim dll before killing window, otherwise anim dll dies too early
    iAnim->Deactivate();
    iAnim->Close();

    iAnimDll->Close();
    
    return aError;
    }

void CProfilerButtonListener::RunL() 
	{	
    // resubscribe before processing new value to prevent missing updates
	IssueRequest();
	
	TInt c = 0;
	if(RProperty::Get(KProfilerKeyEventPropertyCat, EProfilerKeyEventPropertySample, c) == KErrNone)
		{
		// do something with event
		LOGSTRING2("CProfilerButtonListener::RunL() - event [%d] received",c);
	
		iSample[0] = c;
		iSample[1] = c >> 8;
		iSample[2] = c >> 16;
		iSample[3] = c >> 24;
		
		// Space for GPP sample time		
		TUint32 sampleTime = User::NTickCount() - iSampleStartTime; 
		LOGSTRING2("CProfilerButtonListener::RunL() - sample time is %d",sampleTime);
		
		iSample[4] = sampleTime;
		iSample[5] = sampleTime >> 8;
		iSample[6] = sampleTime >> 16;
		iSample[7] = sampleTime >> 24;
		
		iSampler->AddSample(iSample, 8, 0xb0);
		}
	}
	
TInt CProfilerButtonListener::StartL()
	{
	LOGTEXT(_L("CProfilerButtonListener::StartL() - Activate touch server dll"));
	TInt err(KErrNone);
	
	// get the property value
	TInt r = RProperty::Get(KGppPropertyCat, EGppPropertySyncSampleNumber, iSampleStartTime);
	if(r != KErrNone)
		{
		LOGSTRING2("CProfilerButtonListener::StartL() - getting iSyncOffset failed, error %d", r);
		}
	
	iAnimDll = new (ELeave) RAnimDll(iWs);
	LOGTEXT(_L("CProfilerButtonListener::StartL() - #1"));
	
	TParse* fp = new (ELeave) TParse();
	CleanupStack::PushL(fp);
	fp->Set( KDllName, &KDC_SHARED_LIB_DIR , NULL );    
	LOGSTRING2("CProfilerButtonListener::StartL() - touch event server: %S" , &(fp->FullName()));

	err = iAnimDll->Load(fp->FullName());
	// check if anim dll load failed
	if(err != KErrNone)
	    {
        CleanupStack::PopAndDestroy(fp);
	    // stop plugin if failed
	    iAnimDll->Close();
	    return KErrGeneral;
	    }
    CleanupStack::PopAndDestroy(fp);
 	LOGTEXT(_L("CProfilerButtonListener::StartL() - #2"));

	iAnim = new (ELeave) RProfilerTouchEventAnim(*iAnimDll);
 	LOGTEXT(_L("CProfilerButtonListener::StartL() - #3"));
	iAnim->ConstructL(iMainWindow->Window());
	
	// activate the animation dll for collecting touch and key events
	iAnim->Activate();

	// wait for a new sample
	IssueRequest();
	
	// hide this window group from the app switcher
	iMainWindow->Client()->Group().SetOrdinalPosition(-1);
	iMainWindow->Client()->Group().EnableReceiptOfFocus(EFalse);
	return KErrNone;
	}

TInt CProfilerButtonListener::Stop() 
	{
	LOGTEXT(_L("CProfilerButtonListener::Stop() - enter"));
	// deactivate the anim dll before killing window, otherwise anim dll dies too early
	iAnim->Deactivate();
	iAnim->Close();

	iAnimDll->Close();

	Cancel();
	LOGTEXT(_L("CProfilerButtonListener::Stop() - exit"));
	return KErrNone;
	}


///////////////////////////////////////////////////////////////////////////////
////////////////////////// CWindow implementation /////////////////////////////
///////////////////////////////////////////////////////////////////////////////

CWindow::CWindow(CWsClient* aClient)
: iClient(aClient)
	{
    LOGTEXT(_L("CWindow::CWindow()"));
	}

void CWindow::ConstructL (const TRect& aRect, CWindow* aParent)
	{
	LOGTEXT(_L("CWindow::ConstructL(): Start"));

	// If a parent window was specified, use it; if not, use the window group
	// (aParent defaults to 0).
	RWindowTreeNode* parent= aParent ? (RWindowTreeNode*) &(aParent->Window()) : &(iClient->iGroup);
	iWindow=RWindow(iClient->iWs); // use app's session to window server
	User::LeaveIfError(iWindow.Construct(*parent,(TUint32)this));
	LOGSTRING2("CWindow::ConstructL(): Start - window handle is: 0x%08x", this);
	iRect = aRect;
	iWindow.SetExtent(iRect.iTl, iRect.Size()); // set extent relative to group coords
	iWindow.Activate(); // window is now active
	LOGTEXT(_L("CWindow::ConstructL(): End"));
	}


CWindow::~CWindow()
	{
    LOGTEXT(_L("CWindow::~CWindow(): Start"));
	iWindow.Close(); // close our window
    LOGTEXT(_L("CWindow::~CWindow(): End"));
	}

RWindow& CWindow::Window()
	{
    LOGTEXT(_L("CWindow::Window()"));
	return iWindow;
	}

CWindowGc* CWindow::SystemGc()
	{
    LOGTEXT(_L("CWindow::SystemGc()"));
	return iClient->iGc;
	}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////// CWsClient implementation ////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
CWsClient::CWsClient()
: CActive(CActive::EPriorityStandard)
	{
    LOGTEXT(_L("CWsClient::CWsClient()"));
	}

void CWsClient::ConstructL()
	{
    LOGTEXT(_L("CWsClient::ConstructL() - Start"));
    TInt r = RProperty::Define(EProfilerKeyEventPropertySample, RProperty::EInt, KAllowAllPolicy, KCapabilityNone);
    if (r!=KErrAlreadyExists)
        {
        User::LeaveIfError(r);
        }
    
	CActiveScheduler::Add(this);

	// attach to 
	User::LeaveIfError(iProperty.Attach(KProfilerKeyEventPropertyCat,EProfilerKeyEventPropertySample));
    
	// get a session going
	User::LeaveIfError(iWs.Connect());

	// construct screen device and graphics context
	iScreen=new (ELeave) CWsScreenDevice(iWs); // make device for this session
	User::LeaveIfError(iScreen->Construct( 0 )); // and complete its construction
	User::LeaveIfError(iScreen->CreateContext(iGc)); // create graphics context

	// construct our one and only window group
	iGroup=RWindowGroup(iWs);
	User::LeaveIfError(iGroup.Construct((TInt)this, EFalse)); // meaningless handle; enable focus
	
	// construct main window
	ConstructMainWindowL();

	LOGTEXT(_L("CWsClient::CWsClient() - End"));
	}

CWsClient::~CWsClient()
	{
    LOGTEXT(_L("CWsClient::~CWsClient() - Start"));
    
	// get rid of everything we allocated
	delete iGc;
	delete iScreen;
	
	iGroup.Close();
	// finish with window server
	iWs.Close();
	
    LOGTEXT(_L("CWsClient::~CWsClient() - Exit"));
	}

void CWsClient::Exit()
	{
    LOGTEXT(_L("CWsClient::Exit() - Start"));

	// destroy window group
	iGroup.Close();
	// finish with window server
    iProperty.Close();
	iWs.Close();
    LOGTEXT(_L("CWsClient::Exit() - Exit"));
	}

void CWsClient::IssueRequest()
	{
    LOGTEXT(_L("CWsClient::IssueRequest() - Start"));
    iProperty.Subscribe( iStatus );
    SetActive(); // so we're now active
    LOGTEXT(_L("CWsClient::IssueRequest() - Exit"));
	}

void CWsClient::DoCancel()
	{
    LOGTEXT(_L("CWsClient::DoCancel() - Start"));
	// clean up the sample property
    iProperty.Cancel();
    iProperty.Close();
    LOGTEXT(_L("CWsClient::DoCancel() - Exit"));
	}

void CWsClient::ConstructMainWindowL()
	{
    LOGTEXT(_L("CWsClient::ConstructMainWindowL()"));
	}