Merge.
// 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:
// streammap.cpp: creates and maintaines the association between native stream and a TSurfaceId
//
//
#include "streammap.h"
#include <graphics/updateserverprovider.h>
#include <e32property.h>
#include <e32std.h>
#include <e32cmn.h>
#include "openwfcpanic.h"
#include "surfacestream.h"
#include "contentupdateproxy.h"
static const TInt KOpenWfcInteropCleanupKey = 0x10286FC5;
TEMPLATE_SPECIALIZATION class RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>
{
public:
inline static TGeneralHashFunction32 Hash();
inline static TGeneralIdentityRelation Id();
};
inline TGeneralHashFunction32 RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Hash()
{return (TGeneralHashFunction32)&DefaultHash::Integer;}
inline TGeneralIdentityRelation RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Id()
{return (TGeneralIdentityRelation)&DefaultIdentity::Integer;}
COpenWfcStreamMap* COpenWfcStreamMap::pInstance = NULL;
TUint32 COpenWfcStreamMap::HashFunction(const TSurfaceId& aHashKey)
{
TPckgC<TSurfaceId> pckg(aHashKey);
return DefaultHash::Des8(pckg);
}
EXPORT_C COpenWfcStreamMap& COpenWfcStreamMap::InstanceL()
{
// would have been nice to try to protect this area with a mutex, however,
// the preliminary analyses show we can guarantee the safe creation of the mutex
// by invoking InstanceL() from the place the CGce instances are created
// If necessary, in future, the code can be expanded by using a named mutex.
if (!pInstance)
{
COpenWfcStreamMap* newInstance = new(ELeave)COpenWfcStreamMap();
CleanupStack::PushL(newInstance);
newInstance->ConstructL();
CleanupStack::Pop(newInstance);
pInstance=newInstance;
}
return *pInstance;
}
EXPORT_C TInt COpenWfcStreamMap::Reserve(TInt aExpand)
{
Guard g(iMutex);
TInt ret = iMap.Reserve(aExpand);
return ret;
}
CSurfaceStream* COpenWfcStreamMap::Find(const TSurfaceId& aSurfaceId)
{
Guard g(iMutex);
CSurfaceStream** ns = iMap.Find(aSurfaceId);
// used if statement to ease debug help
if (ns)
{
(*ns)->AddReference();
return *ns;
}
return NULL;
}
CSurfaceStream* COpenWfcStreamMap::AcquireL(const TSurfaceId& aSurfaceId)
{
Guard* pGuard = new(ELeave) Guard(iMutex);
User::LeaveIfNull(pGuard);
CleanupDeletePushL(pGuard);
CSurfaceStream** ns = NULL;
CSurfaceStream* ret = NULL;
ns = iMap.Find(aSurfaceId);
if (ns)
{
WFCI_ASSERT_DEBUG((*ns), EOwfPanicInvalidHasMap); // should have never happened
ret = *ns;
}
else
{
ret = CSurfaceStream::NewLC(aSurfaceId);
User::LeaveIfError(iMap.Insert(aSurfaceId, ret));
CleanupStack::Pop();
}
ret->AddReference();
CleanupStack::PopAndDestroy(pGuard);
return ret;
}
EXPORT_C TInt COpenWfcStreamMap::Count()
{
Guard g(iMutex);
TInt count = iMap.Count();
return count;
}
RSurfaceManager& COpenWfcStreamMap::SurfaceManager()
{
return iSurfaceManager;
}
TInt COpenWfcStreamMap::LockDestroy(CSurfaceStream* aStream)
{
Guard g(iMutex);
TInt ret = KErrNone;
if (aStream)
{
if (aStream->RemainingReference())
{
const TSurfaceId& surfaceId = aStream->SurfaceId();
CSurfaceStream** ns = iMap.Find(surfaceId);
// used if statement to ease debug help
if (ns && ((*ns) == aStream))
{
TInt ret = iMap.Remove(surfaceId);
delete aStream;
}
else
{
ret = KErrNotFound;
}
}
else // RemainingReference
{
ret = KErrInUse;
}
}
else // aStream
{
ret = KErrArgument;
}
return ret;
}
COpenWfcStreamMap::COpenWfcStreamMap():
iMap(THashFunction32<TSurfaceId>(COpenWfcStreamMap::HashFunction), TIdentityRelation<TSurfaceId>()),
iRegisteredUpdaters()
{
}
TInt COpenWfcStreamMap::DeleteSingleton(TAny* aData)
/**
* aData A pointer to the heap registered for this callback
*/
{
// Blank the property for this callback
RThread t;
RProperty prop;
TCallBack cb(NULL, NULL);
TPckgC<TCallBack> cbPckg(cb);
prop.Set(TUid::Uid(t.SecureId().iId), KOpenWfcInteropCleanupKey, cbPckg);
prop.Close();
t.Close();
if (aData == &User::Heap())
{
delete pInstance;
pInstance = NULL;
return ETrue;
}
return EFalse;
}
COpenWfcStreamMap::~COpenWfcStreamMap()
{
iMutex.Wait();
{
THashMapIter<TSurfaceId, CSurfaceStream*> iter(iMap);
const TSurfaceId* nextKey = iter.NextKey();
CSurfaceStream* const* ns = NULL;
while (nextKey)
{
ns = iter.NextValue();
if (ns && *ns)
{
delete (*ns);
}
nextKey = iter.NextKey();
}
}
iMap.Close();
iSurfaceManager.Close();
iMutex.Signal();
iMutex.Close();
{
THashMapIter<TInt32, CExtensionContainer*> iter(iRegisteredUpdaters);
const TInt32* nextKey = iter.NextKey();
CExtensionContainer* const* extensionContainer = NULL;
while (nextKey)
{
extensionContainer = iter.NextValue();
if (extensionContainer && *extensionContainer)
{
delete (*extensionContainer);
}
nextKey = iter.NextKey();
}
}
iRegisteredUpdaters.Close();
}
COpenWfcStreamMap::COpenWfcStreamMap(const COpenWfcStreamMap&)
{
Panic(EOwfPanicInvalidCallStreamMap);
}
COpenWfcStreamMap& COpenWfcStreamMap::operator= (const COpenWfcStreamMap&)
{
Panic(EOwfPanicInvalidCallStreamMap);
return *this;
}
void COpenWfcStreamMap::ConstructL()
{
User::LeaveIfError(iMutex.CreateLocal());
iMap.Reserve(iInitialSize);
TSurfaceId surface = TSurfaceId::CreateNullId();
User::LeaveIfError(iMap.Insert(surface, NULL));
User::LeaveIfError(iSurfaceManager.Open());
RProcess process;
TUidType uidType = process.Type();
const TInt32 KWservUid = 268450592;
const TUid& uid1 = uidType[2];
if(uid1.iUid == KWservUid) //only wserv process can start the server
{
StartSurfaceUpdateServer(iSurfUpdateServ);
}
// Register the cleanup function in a property defined by WServ
RThread t;
TUid category = {t.SecureId().iId};
RProperty prop;
TCallBack cb(DeleteSingleton, &User::Heap());
TPckgC<TCallBack> cbPckg(cb);
// If the property cannot be set the assumption is that the cleanup is not needed
(void) prop.Set(category, KOpenWfcInteropCleanupKey, cbPckg);
prop.Close();
t.Close();
// StreamMap is constructed from main thread
SetMainHeap();
}
COpenWfcStreamMap::Guard::Guard(RFastLock& aLock):
iLock(aLock)
{
iLock.Wait();
}
COpenWfcStreamMap::Guard::~Guard()
{
iLock.Signal();
}
EXPORT_C RHeap* COpenWfcStreamMap::GetMainHeap()
{
return iMainHeap;
}
void COpenWfcStreamMap::SetMainHeap()
{
iMainHeap = &User::Heap();
}
TInt COpenWfcStreamMap::RegisterScreenNotifications(TInt aScreenNum, TInt aPriority,TInt aInternalVersion)
{
COpenWfcStreamMap* pInstance = NULL;
TRAPD(err,pInstance = &COpenWfcStreamMap::InstanceL());
if (err != KErrNone)
{
return err;
}
if (iRegisteredUpdaters.Find(aScreenNum)!= NULL)
{
return KErrAlreadyExists;
}
CExtensionContainer* updateProxy = NULL;
TRAP(err, updateProxy = CContentUpdateProxy::NewL(aScreenNum, pInstance,aInternalVersion,aPriority));
if (err)
{
return err;
}
if ((err = iRegisteredUpdaters.Insert(aScreenNum, updateProxy)) != KErrNone)
{
delete updateProxy;
return err;
}
if (!pInstance->iSurfUpdateServ)
{
return KErrNotReady; //For testing purposes the backend proxy still exists.
}
err = iSurfUpdateServ->Register(aScreenNum, updateProxy, aPriority);
if (err!=KErrNone)
{
delete updateProxy;
iRegisteredUpdaters.Remove(aScreenNum);
}
return err;
}
CExtensionContainer* COpenWfcStreamMap::RegisteredScreenNotifications(TInt aScreenNum)
{
return *iRegisteredUpdaters.Find(aScreenNum);
}
TInt COpenWfcStreamMap::UnregisterScreenNotifications(TInt aScreenNum)
{
TInt err = KErrNone;
CExtensionContainer** backend = iRegisteredUpdaters.Find(aScreenNum);
if (backend)
{
delete *backend;
iRegisteredUpdaters.Remove(aScreenNum);
if (iSurfUpdateServ)
{
err = iSurfUpdateServ->Register(aScreenNum, NULL, 0);
}
else
{
err = KErrNotReady;
}
}
else
{
err = KErrNotFound;
}
return err;
}