sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // streammap.cpp: creates and maintaines the association between native stream and a TSurfaceId sl@0: // sl@0: // sl@0: sl@0: #include "streammap.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "openwfcpanic.h" sl@0: #include "surfacestream.h" sl@0: #include "contentupdateproxy.h" sl@0: sl@0: static const TInt KOpenWfcInteropCleanupKey = 0x10286FC5; sl@0: sl@0: COpenWfcStreamMap* COpenWfcStreamMap::pInstance = NULL; sl@0: sl@0: TUint32 COpenWfcStreamMap::HashFunction(const TSurfaceId& aHashKey) sl@0: { sl@0: TPckgC pckg(aHashKey); sl@0: return DefaultHash::Des8(pckg); sl@0: } sl@0: sl@0: EXPORT_C COpenWfcStreamMap& COpenWfcStreamMap::InstanceL() sl@0: { sl@0: // would have been nice to try to protect this area with a mutex, however, sl@0: // the preliminary analyses show we can guarantee the safe creation of the mutex sl@0: // by invoking InstanceL() from the place the CGce instances are created sl@0: // If necessary, in future, the code can be expanded by using a named mutex. sl@0: if (!pInstance) sl@0: { sl@0: COpenWfcStreamMap* newInstance = new(ELeave)COpenWfcStreamMap(); sl@0: CleanupStack::PushL(newInstance); sl@0: newInstance->ConstructL(); sl@0: CleanupStack::Pop(newInstance); sl@0: pInstance=newInstance; sl@0: } sl@0: return *pInstance; sl@0: } sl@0: sl@0: CSurfaceStream* COpenWfcStreamMap::Find(const TSurfaceId& aSurfaceId) sl@0: { sl@0: Guard g(iMutex); sl@0: CSurfaceStream** ns = iMap.Find(aSurfaceId); sl@0: // used if statement to ease debug help sl@0: if (ns) sl@0: { sl@0: (*ns)->AddReference(); sl@0: return *ns; sl@0: } sl@0: return NULL; sl@0: } sl@0: sl@0: CSurfaceStream* COpenWfcStreamMap::AcquireL(const TSurfaceId& aSurfaceId) sl@0: { sl@0: Guard* pGuard = new(ELeave) Guard(iMutex); sl@0: User::LeaveIfNull(pGuard); sl@0: CleanupDeletePushL(pGuard); sl@0: sl@0: CSurfaceStream** ns = NULL; sl@0: CSurfaceStream* ret = NULL; sl@0: ns = iMap.Find(aSurfaceId); sl@0: if (ns) sl@0: { sl@0: WFCI_ASSERT_DEBUG((*ns), EOwfPanicInvalidHasMap); // should have never happened sl@0: ret = *ns; sl@0: } sl@0: else sl@0: { sl@0: ret = CSurfaceStream::NewLC(aSurfaceId); sl@0: User::LeaveIfError(iMap.Insert(aSurfaceId, ret)); sl@0: CleanupStack::Pop(); sl@0: } sl@0: ret->AddReference(); sl@0: CleanupStack::PopAndDestroy(pGuard); sl@0: return ret; sl@0: } sl@0: sl@0: EXPORT_C TInt COpenWfcStreamMap::Count() sl@0: { sl@0: Guard g(iMutex); sl@0: TInt count = iMap.Count(); sl@0: return count; sl@0: } sl@0: sl@0: EXPORT_C RSurfaceManager& COpenWfcStreamMap::SurfaceManager() sl@0: { sl@0: WFCI_ASSERT_DEBUG(iSurfaceManager, EOwfPanicInvalidHasMap); sl@0: return *iSurfaceManager; sl@0: } sl@0: sl@0: TInt COpenWfcStreamMap::LockDestroy(CSurfaceStream* aStream) sl@0: { sl@0: Guard g(iMutex); sl@0: TInt ret = KErrNone; sl@0: if (aStream) sl@0: { sl@0: if (aStream->RemainingReference()) sl@0: { sl@0: const TSurfaceId& surfaceId = aStream->SurfaceId(); sl@0: CSurfaceStream** ns = iMap.Find(surfaceId); sl@0: // used if statement to ease debug help sl@0: if (ns && ((*ns) == aStream)) sl@0: { sl@0: TInt ret = iMap.Remove(surfaceId); sl@0: delete aStream; sl@0: } sl@0: else sl@0: { sl@0: ret = KErrNotFound; sl@0: } sl@0: } sl@0: else // RemainingReference sl@0: { sl@0: ret = KErrInUse; sl@0: } sl@0: } sl@0: else // aStream sl@0: { sl@0: ret = KErrArgument; sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: COpenWfcStreamMap::COpenWfcStreamMap(): sl@0: iMap(THashFunction32(COpenWfcStreamMap::HashFunction), TIdentityRelation()), sl@0: iSurfaceManager(NULL), sl@0: iRegisteredUpdaters() sl@0: { sl@0: } sl@0: sl@0: TInt COpenWfcStreamMap::DeleteSingleton(TAny* aData) sl@0: /** sl@0: * aData A pointer to the heap registered for this callback sl@0: */ sl@0: { sl@0: // Blank the property for this callback sl@0: RThread t; sl@0: RProperty prop; sl@0: TCallBack cb(NULL, NULL); sl@0: TPckgC cbPckg(cb); sl@0: prop.Set(TUid::Uid(t.SecureId().iId), KOpenWfcInteropCleanupKey, cbPckg); sl@0: prop.Close(); sl@0: t.Close(); sl@0: sl@0: if (aData == &User::Heap()) sl@0: { sl@0: delete pInstance; sl@0: pInstance = NULL; sl@0: return ETrue; sl@0: } sl@0: return EFalse; sl@0: } sl@0: sl@0: COpenWfcStreamMap::~COpenWfcStreamMap() sl@0: { sl@0: iMutex.Wait(); sl@0: { sl@0: THashMapIter iter(iMap); sl@0: const TSurfaceId* nextKey = iter.NextKey(); sl@0: CSurfaceStream* const* ns = NULL; sl@0: while (nextKey) sl@0: { sl@0: ns = iter.CurrentValue(); sl@0: if (ns && *ns) sl@0: { sl@0: delete (*ns); sl@0: } sl@0: nextKey = iter.NextKey(); sl@0: } sl@0: } sl@0: iMap.Close(); sl@0: if (iSurfaceManager) sl@0: { sl@0: iSurfaceManager->Close(); sl@0: delete iSurfaceManager; sl@0: iSurfaceManager = NULL; sl@0: } sl@0: iMutex.Signal(); sl@0: iMutex.Close(); sl@0: sl@0: { sl@0: THashMapIter iter(iRegisteredUpdaters); sl@0: const TInt32* nextKey = iter.NextKey(); sl@0: CExtensionContainer* const* extensionContainer = NULL; sl@0: while (nextKey) sl@0: { sl@0: extensionContainer = iter.CurrentValue(); sl@0: if (extensionContainer && *extensionContainer) sl@0: { sl@0: delete (*extensionContainer); sl@0: } sl@0: nextKey = iter.NextKey(); sl@0: } sl@0: } sl@0: iRegisteredUpdaters.Close(); sl@0: } sl@0: sl@0: void COpenWfcStreamMap::ConstructL() sl@0: { sl@0: User::LeaveIfError(iMutex.CreateLocal()); sl@0: iMap.Reserve(iInitialSize); sl@0: TSurfaceId surface = TSurfaceId::CreateNullId(); sl@0: User::LeaveIfError(iMap.Insert(surface, NULL)); sl@0: sl@0: iSurfaceManager = new(ELeave) RSurfaceManager(); sl@0: User::LeaveIfError(iSurfaceManager->Open()); sl@0: RProcess process; sl@0: TUidType uidType = process.Type(); sl@0: const TInt32 KWservUid = 268450592; sl@0: const TUid& uid1 = uidType[2]; sl@0: sl@0: if(uid1.iUid == KWservUid) //only wserv process can start the server sl@0: { sl@0: StartSurfaceUpdateServer(iSurfUpdateServ); sl@0: } sl@0: sl@0: // Register the cleanup function in a property defined by WServ sl@0: RThread t; sl@0: TUid category = {t.SecureId().iId}; sl@0: RProperty prop; sl@0: TCallBack cb(DeleteSingleton, &User::Heap()); sl@0: TPckgC cbPckg(cb); sl@0: sl@0: // If the property cannot be set the assumption is that the cleanup is not needed sl@0: (void) prop.Set(category, KOpenWfcInteropCleanupKey, cbPckg); sl@0: prop.Close(); sl@0: t.Close(); sl@0: sl@0: // StreamMap is constructed from main thread sl@0: SetMainHeap(); sl@0: } sl@0: sl@0: COpenWfcStreamMap::Guard::Guard(RFastLock& aLock): sl@0: iLock(aLock) sl@0: { sl@0: iLock.Wait(); sl@0: } sl@0: sl@0: COpenWfcStreamMap::Guard::~Guard() sl@0: { sl@0: iLock.Signal(); sl@0: } sl@0: sl@0: EXPORT_C RHeap* COpenWfcStreamMap::GetMainHeap() sl@0: { sl@0: return iMainHeap; sl@0: } sl@0: sl@0: void COpenWfcStreamMap::SetMainHeap() sl@0: { sl@0: iMainHeap = &User::Heap(); sl@0: } sl@0: sl@0: TInt COpenWfcStreamMap::RegisterScreenNotifications(TInt aScreenNum, TInt aPriority,TInt aInternalVersion) sl@0: { sl@0: COpenWfcStreamMap* pInstance = NULL; sl@0: TRAPD(err,pInstance = &COpenWfcStreamMap::InstanceL()); sl@0: if (err != KErrNone) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: if (iRegisteredUpdaters.Find(aScreenNum)!= NULL) sl@0: { sl@0: return KErrAlreadyExists; sl@0: } sl@0: sl@0: CExtensionContainer* updateProxy = NULL; sl@0: TRAP(err, updateProxy = CContentUpdateProxy::NewL(aScreenNum, pInstance,aInternalVersion,aPriority)); sl@0: if (err) sl@0: { sl@0: return err; sl@0: } sl@0: sl@0: if ((err = iRegisteredUpdaters.Insert(aScreenNum, updateProxy)) != KErrNone) sl@0: { sl@0: delete updateProxy; sl@0: return err; sl@0: } sl@0: sl@0: if (!pInstance->iSurfUpdateServ) sl@0: { sl@0: return KErrNotReady; //For testing purposes the backend proxy still exists. sl@0: } sl@0: err = iSurfUpdateServ->Register(aScreenNum, updateProxy, aPriority); sl@0: if (err!=KErrNone) sl@0: { sl@0: delete updateProxy; sl@0: iRegisteredUpdaters.Remove(aScreenNum); sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: CExtensionContainer* COpenWfcStreamMap::RegisteredScreenNotifications(TInt aScreenNum) sl@0: { sl@0: return *iRegisteredUpdaters.Find(aScreenNum); sl@0: } sl@0: sl@0: TInt COpenWfcStreamMap::UnregisterScreenNotifications(TInt aScreenNum) sl@0: { sl@0: TInt err = KErrNone; sl@0: CExtensionContainer** backend = iRegisteredUpdaters.Find(aScreenNum); sl@0: if (backend) sl@0: { sl@0: delete *backend; sl@0: iRegisteredUpdaters.Remove(aScreenNum); sl@0: if (iSurfUpdateServ) sl@0: { sl@0: err = iSurfUpdateServ->Register(aScreenNum, NULL, 0); sl@0: } sl@0: else sl@0: { sl@0: err = KErrNotReady; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: err = KErrNotFound; sl@0: } sl@0: sl@0: return err; sl@0: }