layouts/cdl/CdlEngine/src/CCdlEngine.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 21:12:52 +0200
changeset 2 abcbdabaa4c5
parent 0 05e9090e2422
child 54 08459e712984
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* 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 "CCdlEngine.h"
#include <CdlEngDef.h>
#include "CdlRefs.h"
#include "CdlServEng.h"



//
// CCdlEngineBase
//

CCdlEngineBase* CCdlEngineBase::Static()
	{
	return static_cast<CCdlEngineBase*>(Dll::Tls());
	}

CCdlEngineBase* CCdlEngineBase::NewLC()
	{
	CCdlEngineBase* self = new(ELeave) CCdlEngineBase;
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CCdlEngineBase* CCdlEngineBase::InstanceLC(TBool& aPushed)
	{
	aPushed = EFalse;
	CCdlEngineBase* eng = CCdlEngineBase::Static();
	if (!eng)
		{
		eng = CCdlEngineBase::NewLC();
		aPushed = ETrue;
		}
	return eng;
	}

CCdlEngineBase::~CCdlEngineBase()
	{
	delete iLibMan;
	Dll::SetTls(0);
	}

void CCdlEngineBase::IncRefCount()
	{
	iRefCount++;
	}

void CCdlEngineBase::DecRefCount()
	{
	iRefCount--;
	if (iRefCount == 0)
		delete this;
	}

CCdlEngineBase::CCdlEngineBase()
	{
	Dll::SetTls(this);
	}

void CCdlEngineBase::ConstructL()
	{
	iLibMan = new(ELeave) CCdlLibManager;
	iLibMan->ConstructL();
	}

CCdlRefCollection* CCdlEngineBase::FileContentsLC(const TDesC& aLibName)
	{
	return CCdlLibraryContentsImp::NewLC(aLibName, this);
	}

CCdlLibManager* CCdlEngineBase::LibMan() const
	{
	return iLibMan;
	}

TInt CCdlEngineBase::IsPluginInRom(const TDesC& /*aFileName*/, TBool& /*aIsInRom*/) const
	{
	return KErrNotSupported;
	}

TInt CCdlEngineBase::PluginDrive(const TDesC& /*aFileName*/, TDriveUnit& /*aDrive*/) const
    {
	return KErrNotSupported;
    }


//
// CCdlEngine
//

CCdlEngine* CCdlEngine::Static()
	{
	return static_cast<CCdlEngine*>(Dll::Tls());
	}

CCdlEngine* CCdlEngine::NewLC()
	{
	CCdlEngine* self = new(ELeave) CCdlEngine;
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CCdlEngine* CCdlEngine::InstanceLC(TBool& aPushed)
	{
	aPushed = EFalse;
	CCdlEngine* eng = CCdlEngine::Static();
	if (!eng)
		{
		eng = CCdlEngine::NewLC();
		aPushed = ETrue;
		}
	return eng;
	}

CCdlEngine& CCdlEngine::Instance()
	{
	CCdlEngine* eng = CCdlEngine::Static();
	__ASSERT_ALWAYS(eng, Panic(ECdlEngPanic_NoEngine));
	return *eng;
	}


CCdlEngine::~CCdlEngine()
	{
	delete iChangeMonitor;
	// Release the hash table
	CCdlCustomisations::TIter iterator(iCustomisations);
	while(iterator.NextKey())
	{
		CCdlCustomisationStack* stack = *(iterator.CurrentValue());
		delete stack;
	}
	
	iCustomisations.Close();
	iServer.Close();
	}

TAny* CCdlEngine::GetData(TUid aCdlUid, TInt aApiId) const
	{
	return LookupP(aCdlUid).GetData(aApiId);
	}

TCdlEngineFunc* CCdlEngine::GetFunction(TUid aCdlUid, TInt aApiId) const
	{
	return LookupP(aCdlUid).GetFunction(aApiId);
	}

CCdlEngine::CCdlEngine()
	{
	}

void CCdlEngine::ConstructL()
	{
	CCdlEngineBase::ConstructL();
	User::LeaveIfError(iServer.Connect());
	iChangeMonitor = new(ELeave) CCdlChangeMonitor(iServer, this);
	}

CCdlCustomisationStack* CCdlEngine::LookupOrCreateL(TUid aCdlUid)
	{
	CCdlCustomisationStack* stack = Lookup(aCdlUid);
	if (!stack)
		{
		stack = CCdlCustomisationStack::NewLC(aCdlUid, this);
		iCustomisations.InsertL(aCdlUid.iUid, stack);
		CleanupStack::Pop(stack);
		}
	return stack;
	}

void CCdlEngine::RequireCustomisationL(const SCdlInterface* aInterfaceParams)
	{
	LookupOrCreateL(aInterfaceParams->iUid)->RequireCustomisationL(aInterfaceParams);
	}

void CCdlEngine::LoadCustomisationL(const TCdlRef& aRef)
	{
	LookupOrCreateL(aRef.iUid)->LoadCustomisationL(aRef);
	}

TBool CCdlEngine::IsCustomisationStarted(const SCdlInterface* aInterfaceParams) const
	{
	CCdlCustomisationStack* stack = Lookup(aInterfaceParams->iUid);
	if (!stack)
		return EFalse;
	return stack->IsCustomisationStarted(aInterfaceParams);
	}

const CCdlInstance& CCdlEngine::CustomisationInstance(TUid aCdlUid) const
	{
	return LookupP(aCdlUid).Top();
	}

CCdlCustomisationStack* CCdlEngine::Lookup(TUid aCdlUid) const
	{
	CCdlCustomisationStack * const * stack = iCustomisations.Find(aCdlUid.iUid);
	if(stack)
		{
		// Found from the hash map
		return *stack;
		}
		
	return NULL;
	}

CCdlCustomisationStack& CCdlEngine::LookupP(TUid aCdlUid) const
	{
	CCdlCustomisationStack* stack = Lookup(aCdlUid);
	__ASSERT_ALWAYS(stack, Panic(ECdlEngPanic_CustomisationNotPresent));
	return *stack;
	}

const CCdlInstance* CCdlEngine::LastAccessedInstance(TUid aCdlUid) const
	{
	return LookupP(aCdlUid).LastAccessedInstance();
	}

const TCdlRef& CCdlEngine::LastAccessedRef(TUid aCdlUid) const
	{
	return LastAccessedInstance(aCdlUid)->Ref();
	}

void CCdlEngine::FileNameRelativeToLastAccessedInstance(TUid aCdlUid, TFileName& aFileName) const
	{
	LastAccessedInstance(aCdlUid)->FileNameRelativeToLastAccessedInstance(aFileName);
	}

TInt CCdlEngine::LastApiId() const
	{
	return iLastApiId;
	}

CCdlRefs* CCdlEngine::FindInstancesLC(TUid aCdlUid) const
	{
	return iServer.FindInstancesLC(aCdlUid);
	}

CCdlRefCollection* CCdlEngine::FileContentsLC(const TDesC& aLibName)
	{
	return iServer.FileContentsLC(aLibName);
	}

CCdlNames* CCdlEngine::FindCustomisationFilesLC() const
	{
	return iServer.FindCustomisationFilesLC();
	}

CCdlRefs* CCdlEngine::AllAvailableRefsLC() const
	{
	return iServer.AllAvailableRefsLC();
	}

TInt CCdlEngine::IsPluginInRom(const TDesC& aFileName, TBool& aIsInRom) const
	{
	return iServer.IsPluginInRom(aFileName, aIsInRom);
	}

TInt CCdlEngine::PluginDrive(const TDesC& aFileName, TDriveUnit& aDrive) const
    {
	return iServer.PluginDrive(aFileName, aDrive);
    }

TInt* CCdlEngine::LastApiRefL(TUid aCdlUid)
	{
	CCdlCustomisationStack* stack = LookupOrCreateL(aCdlUid);
	return stack->LastApiRef();
	}

void CCdlEngine::SetLocalStateL(const CCdlRefs& aState)
	{
	CCdlUids* uids = CCdlUids::NewLC();
	TRAPD(err, DoSetLocalStateL(aState, *uids));
	iObservers.HandleCustomisationChangeL(*uids);
	CleanupStack::PopAndDestroy();
	User::LeaveIfError(err);
	}

void CCdlEngine::DoSetLocalStateL(const CCdlRefs& aState, CCdlUids& aChangedUids)
	{
	CCdlUids* uids = aState.UidsLC();
	TInt uidCount = uids->Count();
	aChangedUids.ResizeL(uidCount, TUid::Uid(0));
	for (TInt ii=0; ii<uidCount; ++ii)
		{
		TUid uid = uids->At(ii);
		CCdlCustomisationStack* stack = LookupOrCreateL(uid);
		stack->ClearOverrides();
		aChangedUids[ii] = uid;
		for (CCdlRefs::TIterator pRef = aState.Begin(uid); pRef != aState.End(); ++pRef)
			{
			stack->LoadCustomisationL(*pRef);
			}
		}
	CleanupStack::PopAndDestroy(uids);
	}

void CCdlEngine::SetGlobalStateL(const CCdlRefs& aState)
	{
	HBufC8* buf = aState.ExportLC();
	iServer.SetCustL(*buf);
	CleanupStack::PopAndDestroy(buf);
	}

CCdlRefs* CCdlEngine::LocalStateLC(const CCdlUids& aCdlUids) const
	{
	CCdlRefs* state = CCdlRefs::NewLC();
	TInt count = aCdlUids.Count();
	for (TInt ii=0; ii<count; ii++)
		{
		TUid uid = aCdlUids[ii];
		AddLocalStateToRefs(uid, state);
		}
	return state;
	}

void CCdlEngine::AddLocalStateToRefs(TUid aUid, CCdlRefs* aState) const
	{
	CCdlCustomisationStack* stack = Lookup(aUid);
	if (stack)
		{
		const CCdlCustomisationStack::CStack& insts = stack->Stack();
		TInt iCount = insts.Count();
		for (TInt jj=0; jj<iCount; jj++)
			{
			aState->AppendL(insts[jj]->Ref());
			}
		}
	}

CCdlRefs* CCdlEngine::GlobalStateLC(const CCdlUids& aCdlUids) const
	{
	TInt size;
	iServer.RequestGetCustL(aCdlUids, size);
	return GlobalStateLC(size);
	}

CCdlRefs* CCdlEngine::GlobalStateLC(TInt aSize) const
	{
	const TInt KMaxRetries = 10;
	CCdlRefs* state = CCdlRefs::NewLC();
	HBufC8* buf = HBufC8::NewMaxLC(aSize);
	TInt ii;
	for (ii=0; ii<KMaxRetries; ii++)
		{
		TPtr8 ptr = buf->Des();
		TInt err = iServer.GetCust(ptr, aSize);
		if (err == KErrNone)
			{
			state->ImportL(ptr);
			CleanupStack::PopAndDestroy(buf);
			break;
			}
		else if (err == KCdlRefsSizeChanged)
			{
			CleanupStack::PopAndDestroy(buf);	// makes ptr invalid
			buf = HBufC8::NewMaxLC(aSize);
			}
		else
			{
			User::Leave(err);
			}
		}

	if (ii == KMaxRetries)
		User::Leave(KErrNotReady);

	return state;
	}

void CCdlEngine::EnableGlobalCustomisationL(const CCdlUids& aCdlUids, TBool aEnabled)
	{
	TInt count = aCdlUids.Count();
	for (TInt ii=0; ii<count; ii++)
		{
		TUid uid = aCdlUids[ii];
		CCdlCustomisationStack* stack = Lookup(uid);
		if (stack)
			{
			stack->EnableGlobalCustomisation(aEnabled);
			}
		}
	StartGlobalCustomisationL();
	}

void CCdlEngine::StartGlobalCustomisationL()
	{
	CCdlUids* add = CCdlUids::NewLC();
	
	CCdlCustomisations::TIter iterator(iCustomisations);
	while(iterator.NextKey())
		{
		CCdlCustomisationStack* stack = *(iterator.CurrentValue());
		TUid uid = stack->Uid();
		TBool isEnabled = (iGloballyCustomised.FindIndex(uid) != KErrNotFound);
		TBool reqEnabled = stack->GlobalCustomisationEnabled();
		if (isEnabled && !reqEnabled)			// enabled, but not required -> remove
			iGloballyCustomised.Remove(uid);
		if (!isEnabled && reqEnabled)			// not enabled, but required -> add
			add->AppendL(uid);
		// other combinations of enabled & required need no action.
		}

	if (add->Count())
		{
		CCdlRefs* state = GlobalStateLC(*add);
		SetLocalStateL(*state);
		CleanupStack::PopAndDestroy(state);
		iGloballyCustomised.AddL(*add);
		}

	iServer.SetUidsToNotifyL(iGloballyCustomised);

	CleanupStack::PopAndDestroy(add);
	}

void CCdlEngine::HandleGlobalCustomisationChangeL(TInt aSize)
	{
	CCdlRefs* state = GlobalStateLC(aSize);
	SetLocalStateL(*state);
	CleanupStack::PopAndDestroy(state);
	}

void CCdlEngine::HandleAvailableRefsChangeL()
	{
	iObservers.HandleAvailableRefsChangeL();
	}

void CCdlEngine::AddCustomisationChangeObserverL(MCdlChangeObserver* aObserver, TUid aUid)
	{
	iObservers.AddCustomisationChangeObserverL(aObserver, aUid);
	}

void CCdlEngine::AddGeneralChangeObserverL(MCdlChangeObserver* aObserver)
	{
	iObservers.AddGeneralChangeObserverL(aObserver);
	}

void CCdlEngine::RemoveChangeObserver(MCdlChangeObserver* aObserver)
	{
	iObservers.RemoveChangeObserver(aObserver);
	}


//
// CCdlLibraryContentsImp
//

CCdlLibraryContentsImp* CCdlLibraryContentsImp::NewLC(const TDesC& aLibName, CCdlEngineBase* aEngine)
	{
	CCdlLibraryContentsImp* self = new(ELeave) CCdlLibraryContentsImp();
	CleanupStack::PushL(self);
	self->ConstructL(aEngine, aLibName);
	return self;
	}

CCdlLibraryContentsImp::~CCdlLibraryContentsImp()
	{
	iLib.Close();
	}

TInt CCdlLibraryContentsImp::CountRefs() const
	{
	return iContent.Count();
	}

TCdlRef CCdlLibraryContentsImp::Ref(TInt aIndex) const
	{
	const SCdlCustomisation& cust = iContent[aIndex];
	TCdlRef ref = 
		{
		cust.iId, 
		{ cust.iInterface->iUid.iUid }, 
		iLib.Lib()->FullName()
		};
	return ref;
	}

void CCdlLibraryContentsImp::ConstructL(CCdlEngineBase* aEngine, const TDesC& aLibName)
	{
	CCdlLibManager* libMan = aEngine->LibMan();
    RCdlLibrary* lib = libMan->FindLib(aLibName);
	iLib = libMan->LoadL(aLibName, lib, EFalse);
	iContent = iLib.Lib()->ContentsL();
	}